d3.js scale donut chart in resize event - javascript

I drew my chart with two dimensions to the width of the window:
var width = (window.innerWidth < 1280) ? 400 : 600,
height = (window.innerWidth < 1280) ? 400 : 500,
radius = Math.min(width, height) / 2;
var arc = d3.svg.arc().innerRadius(radius).outerRadius(radius - 10),
arcFinal = d3.svg.arc().innerRadius(radius - 100).outerRadius(radius - 10),
arcHover = d3.svg.arc().innerRadius(radius - 100).outerRadius(radius);
var svg = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("id", "pie")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");}
What is the best way to update this function in resize event?

Ok, I fixed by adding:
...
var svg = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", "0, 0, " + width + ", " + height)
.attr("preserveAspectRatio", "xMinYMin")
...
Then I updated the width and height on resize event

Related

How to resize d3 map

I have this map in d3 consisting of a chart and map:
I define a few global variables:
var chartWidth = window.innerWidth * 0.425,
chartHeight = 473,
leftPadding = 35,
rightPadding = 2,
topBottomPadding = 5,
innerWidth = chartWidth - leftPadding - rightPadding,
innerHeight = chartHeight - topBottomPadding * 2,
translate = "translate(" + leftPadding + "," + topBottomPadding + ")";
Here's the map:
//set up the map
function setMap(){
var width = window.innerWidth * 0.55, //dimensions
height = 580; //dimensions
//create new svg container for the map
var map = d3.select("body")
.append("svg")
.attr("class", "map")
.attr("width", width)
.attr("height", height);
And a linked chart:
function setChart(csvData, colorScale, attribute){
var expressed = attribute
//create a second svg element to hold the bar chart
var chart = d3.select("body")
.append("svg")
.attr("width", chartWidth)
.attr("height", chartHeight)
//assign class
.attr("class", "chart");
//create a rectangle for chart background fill
var chartBackground = chart.append("rect")
.attr("class", "chartBackground")
.attr("width", innerWidth)
.attr("height", innerHeight)
.attr("transform", translate);
}
I'm trying to make the map (the map itself and the associated chart, both are appended to 'map' canvas) responsive, so it will resize when window is resized. I've inserted the following code in the setMap function with no luck, hoping to re-class the 'map' on re-size:
d3.select("map")
.append("div")
.classed("svg-container", true) //container class to make it responsive
.append("svg")
//responsive SVG needs these 2 attributes and no width and height attr
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", "0 0 " + width + " " + height)
//class to make it responsive
.classed("svg-content-responsive", true);
What can I try to achieve this?

Using keydown event with d3.drag () to rotate a SVG

I have a SVG and I want to apply rotation transformation on it but not just with the mouse drag, instead with a mouse drag while pressing the alt key. I have tried to implement something but things donot seem to work as I want. Below is what i have implemented. How can I get the SVG rotated on dragging the mouse while pressing the alt key?
var width = 590, height = 400;
var svg = d3.select("#sketch4").append("svg")
.attr("width", width)
.attr("height", height)
//.call(d3.zoom().on("zoom", zoomed))
.call(d3.drag().on('drag', dragged))
.append("g")
var rect = svg.append("rect")
.attr("x", 100)
.attr("y", 100)
.attr("width", 60)
.attr("height", 30)
.attr("fill", "green")
function dragged() {
if (d3.event.sourceEvent.altKey){
var me = sketchSVG.node()
var x1 = me.getBBox().x + me.getBBox().width/2;
var y1 = me.getBBox().y + me.getBBox().height/2;
sketchSVG.attr("transform","rotate("+d3.event.y+","+x1+","+y1+")" );
metricSVG.attr("transform","rotate("+d3.event.y+","+x1+","+y1+")" );
}
};
You need to use d3.event.sourceEvent.x and d3.event.sourceEvent.y. Changing that should get your code working.
To move/zoom your element, create and else condition and just use sketchSVG.attr("transform",d3.event.transform) for zooming and translating the element.
var width = 590,
height = 400;
var svg = d3.select("#sketch4").append("svg")
.attr("width", width)
.attr('id', 'sketchSvg')
.attr("height", height)
.append("g")
d3.select('#sketchSvg')
.call(d3.zoom().on("zoom", dragged))
var rect = svg.append("rect")
.attr("x", 100)
.attr("y", 100)
.attr("width", 60)
.attr("height", 30)
.attr("fill", "green")
function dragged(d) {
if (d3.event.sourceEvent.altKey && d3.event.sourceEvent.type == 'mousemove') {
var me = svg.node()
var x1 = me.getBBox().x + me.getBBox().width / 2;
var y1 = me.getBBox().y + me.getBBox().height / 2;
svg.attr("transform", "rotate(" + d3.event.sourceEvent.y + "," + x1 + "," + y1 + ")");
}
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<div id='sketch4'></div>
Here's one on JSFiddle

How to position the legend to the right of the donut chart

Here is my plunkr code, in this position of the legend is at center, how do I position it to the right of the donut chart?
var svg = d3.select('#chart')
.append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + (width / 2 - radius) +
',' + (height / 2 - radius) + ')');
I tried with the above code but it's not working.
Define new variable and set your legend width in pixels:
var legendWidth = 150;
Use this variable for svg element width:
var svg = d3.select('#chart')
.append('svg')
.attr('width', width + legendWidth) // <== !!!
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + (width / 2) +
',' + (height / 2) + ')');
Rewrite your function for legend transform attribute this way:
var legend = svg.selectAll('.legend')
.data(color.domain())
.enter()
.append('g')
.attr('class', 'legend')
.attr('transform', function(d, i) {
var height = legendRectSize + legendSpacing;
var offset = height * color.domain().length / 2;
var vert = i * height - offset;
return 'translate(' + width / 2 + ',' + vert + ')'; // <== move every legend item on half of width
});
Check working example here.
Checkout this version of your jsfiddle. I have corrected some calculation to show legend on right side. highlighted code change below.
// For increasing horizontal space
var width = 600;
// For arranging chart in full space
var svg = d3.select('#chart')
.append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + (width / 4) +
',' + (height / 2) + ')');
// For moving legend to right
var legend = svg.selectAll('.legend')
.data(color.domain())
.enter()
.append('g')
.attr('class', 'legend')
.attr('transform', function(d, i) {
var height = legendRectSize + legendSpacing;
var offset = height * color.domain().length / 2;
var horz = 7 * legendRectSize;

scale size donut in d3.js

I have this donut, and I want to make everything small, want to make a size of 70px - 70px, but do not know how to apply a scale. I have also the problem that the label "svg" also has great measures. altogether I want to have a square of 70px - 70px with the donut.
var dataset = {
datos: [(50), (50)],
};
var width = 460,
height = 300,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.range(["#38C956", "#000000"]);
var pie = d3.layout.pie()
.sort(null);
var arc = d3.svg.arc()
.innerRadius(radius - 100)
.outerRadius(radius - 50);
var svg = d3.select("#donut").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
var path = svg.selectAll("path")
.data(pie(dataset.datos))
.enter().append("path")
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
http://jsfiddle.net/o11ce/7qoj49br/
the svg is 460 * 300 ... i need 70px x 70px
it would be possible that the edge is not too thick?
You want to scale, can you not just adjust the outer and inner radius ?
Updated fiddle : http://jsfiddle.net/reko91/7qoj49br/1/
Here I have created some variables :
var donutWidth = 10;
var outerRadius = 70;
And used these for both radius':
var arc = d3.svg.arc()
.innerRadius(outerRadius - donutWidth)
.outerRadius(outerRadius);
Just adjust the outerRadius for the size of the donut, and the donutWidth for the width of the donut.
var dataset = {
datos: [(50), (50)],
};
var width = 460,
height = 300,
radius = Math.min(width, height) / 2;
var donutWidth = 10;
var outerRadius = 70;
var color = d3.scale.ordinal()
.range(["#38C956", "#000000"]);
var pie = d3.layout.pie()
.sort(null);
var arc = d3.svg.arc()
.innerRadius(outerRadius - donutWidth)
.outerRadius(outerRadius);
var svg = d3.select("#donut").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
var path = svg.selectAll("path")
.data(pie(dataset.datos))
.enter().append("path")
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<body>
<div id='donut'>
</div>
</body>
Just scale the group element 0.35 (70/200 where 200 is the current size).
var svg = d3.select("#donut").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ") scale(0.35)")
var dataset = {
datos: [(50), (50)],
};
var width = 460,
height = 300,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.range(["#38C956", "#000000"]);
var pie = d3.layout.pie()
.sort(null);
var arc = d3.svg.arc()
.innerRadius(radius - 100)
.outerRadius(radius - 50);
var svg = d3.select("#donut").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ") scale(0.35)")
var path = svg.selectAll("path")
.data(pie(dataset.datos))
.enter().append("path")
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<body>
<div id='donut'>
</div>
</body>

Internet Explorer Scaling not working properly

I have a map created with d3. I set it to have the width of the parent div (with id map) and height with a ratio of 5/9 to to the width. The viewBox has been set to "0 0 width height".
Here is the setup:
var width = $("#map").width(),
height = width * 500 / 900,
active = d3.select(null);
var projection = d3.geo.albersUsa()
.scale(width)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
projection = d3.geo.albersUsa()
.scale(width)
.translate([width / 2, height / 2]);
path = d3.geo.path()
.projection(projection);
svg = d3.select("#map").append("svg")
.attr("width", "100%")
.attr("height", "100%")
.attr("viewBox", "0 0 " + width + " " + height)
g = svg.append("g");
Here is how it looks like in Chrome:
But it looks like this in IE:
The scaling is completely messed up. I believe it has to do with the viewBox. Could someone explain how to solve this issue?
Thanks!
The problem you are having is that height: "100%" is handled differently by Chrome and IE. You have smartly set your height variable to be based on your width and aspect ratio, but to take advantage of this, you'll need to use these values when setting the dimensions of your svg as well as the viewBox:
var svg = d3.select("#map").append("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", "0 0 " + width + " " + height);

Categories