I have a pie chart that was made with d3js.
The data is read from an url.
I want to use the same code to generate the chart, changing the colors of the chart and the data, but I am not managing how can I do.
In witch regard changing the data, the only variable that change its name is earth_footprint, that will be IHD.
Here there is the fiddle of how the code is today.
In this fiddle there are the div on where I want to have my second chart:
<div id="donut2"></div>
And the data that i want to use to the second chart is on this link.
Thanks a lot!!
make a function that encloses everything in your code and make two function calls
function drawChart(url, id, key) {
d3.json(url)
.then(function(data) {
data = data.filter(dataPoint => dataPoint.year == 2015);
const heightValue = 300;
const widthValue = 600;
const strokeWidth = 1.5;
const margin = {
top: 0,
bottom: 20,
left: 30,
right: 20
};
var width = 600 - margin.left - margin.right - (strokeWidth * 2);
var height = 250 - margin.top - margin.bottom;
var radius = Math.min(width, height) / 2;
var color = d3.scaleOrdinal()
.range(["#e688a1", "#ed9a73", "#e3c878", "#64b2cd", "#e1b12c", "red", "green", "violet", "steelblue"]);
var pie = d3.pie()
.value(function(d) {
return d[key];
})(data);
var arc = d3.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var svg =
d3
.select(id)
.append("svg")
.attr("viewBox", `0 0 ${widthValue} ${heightValue}`)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var g = svg.selectAll("arc")
.data(pie)
.enter().append("g")
.attr("class", "arc")
g.on('mouseover', function(d, i) {
d3.select(this).transition()
.duration('50')
.attr('opacity', '.95')
.attr("stroke", "#23374d")
g.append("text")
.attr("class", "text remove")
.style("text-anchor", "middle")
.attr("stroke", "#23374d")
.attr("fill", "#23374d")
.text(d.data.country_name)
})
.on('mouseout', function(d, i) {
d3.select(this).transition()
.duration('50')
.attr('opacity', '1')
.attr("stroke", "none")
g.select(".text.remove").remove();
})
.attr('transform', 'translate(0, 0)');
g.append("path")
.attr("d", arc)
.style("fill", function(d) {
return color(d.data.country_name);
});
g
.append("text")
.attr("text-anchor", "middle")
.attr("x", function(d) {
var a = d.startAngle + (d.endAngle - d.startAngle) / 2 - Math.PI / 2;
d.cx = Math.cos(a) * (radius - 45);
return d.x = Math.cos(a) * (radius + 30);
})
.attr("y", function(d) {
var a = d.startAngle + (d.endAngle - d.startAngle) / 2 - Math.PI / 2;
d.cy = Math.sin(a) * (radius - 12);
return d.y = Math.sin(a) * (radius - 5);
})
.text(function(d) {
return d.value.toFixed(2);
})
.each(function(d) {
var bbox = this.getBBox();
d.sx = d.x - bbox.width / 2 - 2;
d.ox = d.x + bbox.width / 2 + 2;
d.sy = d.oy = d.y + 5;
});
g.append("path")
.attr("class", "pointer")
.style("fill", "none")
.style("stroke", "#2c3e50")
.attr("d", function(d) {
if (d.cx > d.ox) {
return "M" + d.sx + "," + d.sy + "L" + d.ox + "," + d.oy + " " + d.cx + "," + d.cy;
} else {
return "M" + d.ox + "," + d.oy + "L" + d.sx + "," + d.sy + " " + d.cx + "," + d.cy;
}
});
});
}
drawChart("https://raw.githubusercontent.com/cvrnogueira/CODWorkData/master/database/topfive/biggestEarthFootprint.json",
"#donut",
"earth_footprint"
)
drawChart("https://raw.githubusercontent.com/cvrnogueira/CODWorkData/master/database/topfive/biggestIHD.json",
"#donut2",
"IHD"
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://d3js.org/d3.v5.min.js"></script>
<title>JS Bin</title>
</head>
<body>
<div id="donut"></div>
<br>
<br>
<div id="donut2"></div>
</body>
</html>
So your function now takes the url, the id upon which to load and the key you want to read from in the data.
I'm working with a modified version of Mike Bostock's Calendar Heatmap (https://bl.ocks.org/mbostock/4063318). In this version, I rotated the calendar and I'm just focusing on a few months (this was helpful: Tweak D3 calendar view example to be vertical with days be ordered left to right, then top to bottom?). See the attached image.
Does anyone have ideas on how to add small font day numbers to each of the day rectangles? They would be font size 8, and in the corners of each day's rectangle. I've been fiddling with it for hours and haven't gotten anywhere.
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var width = 550,
height = 750,
cellSize = 45;
var formatPercent = d3.format(".1%");
var color = d3.scaleQuantize()
.domain([0, 100])
.range(["#ffffff","#e6f7ff","#b3e6ff","#99ddff","#66ccff","#4dc3ff","#1ab2ff","#0077b3","#004466"]);
var month_strings = ["January", "February", "March"]
var svg = d3.select("body")
.selectAll("svg")
.data([2018])
.enter().append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + ((width - cellSize * 5) / 2) + "," + (height - cellSize * 16 - 1) + ")");
svg.append("text")
.attr("transform", "translate(-10," + cellSize * 3 + ")rotate(-90)")
.attr("font-family", "sans-serif")
.attr("font-size", 20)
.attr("text-anchor", "middle")
.text(month_strings[0]);
svg.append("text")
.attr("transform", "translate(-10," + cellSize * 7 + ")rotate(-90)")
.attr("font-family", "sans-serif")
.attr("font-size", 20)
.attr("text-anchor", "middle")
.text(month_strings[1]);
svg.append("text")
.attr("transform", "translate(-10," + cellSize * 11 + ")rotate(-90)")
.attr("font-family", "sans-serif")
.attr("font-size", 20)
.attr("text-anchor", "middle")
.text(month_strings[2]);
var rect = svg.append("g")
.attr("fill", "none")
.attr("stroke", "#d2d4d8")
.selectAll("rect")
.data(function(d) { return d3.timeDays(new Date(2018, 0, 1), new Date(2018, 3, 1)); })
.enter().append("rect")
.attr("width", cellSize)
.attr("height", cellSize)
.attr("class", "hour bordered")
.attr("rx", 4)
.attr("ry", 4)
//.attr("x", function(d) { return d3.timeWeek.count(d3.timeYear(d), d) * cellSize; })
//.attr("y", function(d) { return d.getDay() * cellSize; })
.attr("x", function(d) { return d.getDay() * cellSize;})
.attr("y", function(d) { return d3.timeWeek.count(d3.timeYear(d), d) * cellSize; })
.datum(d3.timeFormat("%Y-%m-%d"));
svg.append("g")
.attr("fill", "none")
.attr("stroke", "#000")
.selectAll("path")
.data(function(d) { return d3.timeMonths(new Date(2018, 0, 1), new Date(2018, 3, 1)); })
.enter().append("path")
.attr("d", pathMonth);
d3.csv("static/test.csv", function(error, csv) {
if (error) throw error;
var data = d3.nest()
.key(function(d) { return d.Date; })
.rollup(function(d) { return (d[0].Close - d[0].Open) / d[0].Open; })
.object(csv);
rect.filter(function(d) { return d in data; })
.attr("fill", function(d) { return color(data[d]); })
.append("title")
.text(function(d) { return d + ": " + formatPercent(data[d]); });
});
function pathMonth(t0) {
var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
d0 = t0.getDay(), w0 = d3.timeWeek.count(d3.timeYear(t0), t0),
d1 = t1.getDay(), w1 = d3.timeWeek.count(d3.timeYear(t1), t1);
return "M" + d0 * cellSize + "," + (w0) * cellSize
+ "H" + 7 * cellSize + "V" + (w1) * cellSize
+ "H" + (d1 + 1) * cellSize + "V" + (w1 + 1) * cellSize
+ "H" + 0 + "V" + (w0 + 1) * cellSize + "H"
+ d0 * cellSize + "Z";
}
var start_box = svg.append("rect")
.attr("x", 225)
.attr("y", 45)
.attr("width", cellSize)
.attr("height", cellSize)
.attr("rx", 4)
.attr("ry", 4)
.attr("class", "hour bordered")
.style("fill", "#FFD700");
</script>
Here is the CSV:
Date,Weekday,Open,Close
2018-01-01,0,1,0
2018-01-02,1,1,1
2018-01-03,2,1,2
2018-01-04,3,1,3
2018-01-05,4,1,4
2018-01-06,5,1,1
2018-01-07,6,1,1
2018-01-08,0,1,7
2018-01-09,1,1,8
2018-01-10,2,1,9
2018-01-11,3,1,10
2018-01-12,4,1,11
2018-01-13,5,1,1
2018-01-14,6,1,1
2018-01-15,0,1,14
2018-01-16,1,1,15
2018-01-17,2,1,16
2018-01-18,3,1,17
2018-01-19,4,1,18
2018-01-20,5,1,1
2018-01-21,6,1,1
2018-01-22,0,1,21
2018-01-23,1,1,22
2018-01-24,2,1,23
2018-01-25,3,1,24
2018-01-26,4,1,25
2018-01-27,5,1,1
2018-01-28,6,1,1
2018-01-29,0,1,28
2018-01-30,1,1,29
2018-01-31,2,1,30
2018-02-01,3,1,31
2018-02-02,4,1,32
2018-02-03,5,1,1
2018-02-04,6,1,1
2018-02-05,0,1,35
2018-02-06,1,1,36
2018-02-07,2,1,37
2018-02-08,3,1,38
2018-02-09,4,1,39
2018-02-10,5,1,1
2018-02-11,6,1,1
2018-02-12,0,1,42
2018-02-13,1,1,43
2018-02-14,2,1,44
2018-02-15,3,1,45
2018-02-16,4,1,46
2018-02-17,5,1,1
2018-02-18,6,1,1
2018-02-19,0,1,49
2018-02-20,1,1,50
2018-02-21,2,1,51
2018-02-22,3,1,52
2018-02-23,4,1,53
2018-02-24,5,1,1
2018-02-25,6,1,1
2018-02-26,0,1,56
2018-02-27,1,1,57
2018-02-28,2,1,58
2018-03-01,3,1,59
2018-03-02,4,1,60
2018-03-03,5,1,1
2018-03-04,6,1,1
2018-03-05,0,1,63
2018-03-06,1,1,64
2018-03-07,2,1,65
2018-03-08,3,1,66
2018-03-09,4,1,67
2018-03-10,5,1,1
2018-03-11,6,1,1
2018-03-12,0,1,70
2018-03-13,1,1,71
2018-03-14,2,1,72
2018-03-15,3,1,73
2018-03-16,4,1,74
2018-03-17,5,1,1
2018-03-18,6,1,1
2018-03-19,0,1,77
2018-03-20,1,1,78
2018-03-21,2,1,79
2018-03-22,3,1,80
2018-03-23,4,1,81
2018-03-24,5,1,1
2018-03-25,6,1,1
2018-03-26,0,1,84
2018-03-27,1,1,85
2018-03-28,2,1,86
2018-03-29,3,1,87
2018-03-30,4,1,88
2018-03-31,5,1,1
I'd do it like this:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var width = 550,
height = 750,
cellSize = 45;
var formatPercent = d3.format(".1%");
var color = d3.scaleQuantize()
.domain([0, 100])
.range(["#ffffff", "#e6f7ff", "#b3e6ff", "#99ddff", "#66ccff", "#4dc3ff", "#1ab2ff", "#0077b3", "#004466"]);
var month_strings = ["January", "February", "March"]
var svg = d3.select("body")
.selectAll("svg")
.data([2018])
.enter().append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + ((width - cellSize * 5) / 2) + "," + (height - cellSize * 16 - 1) + ")");
svg.append("text")
.attr("transform", "translate(-10," + cellSize * 3 + ")rotate(-90)")
.attr("font-family", "sans-serif")
.attr("font-size", 20)
.attr("text-anchor", "middle")
.text(month_strings[0]);
svg.append("text")
.attr("transform", "translate(-10," + cellSize * 7 + ")rotate(-90)")
.attr("font-family", "sans-serif")
.attr("font-size", 20)
.attr("text-anchor", "middle")
.text(month_strings[1]);
svg.append("text")
.attr("transform", "translate(-10," + cellSize * 11 + ")rotate(-90)")
.attr("font-family", "sans-serif")
.attr("font-size", 20)
.attr("text-anchor", "middle")
.text(month_strings[2]);
var g = svg.append("g")
.attr("fill", "none")
.attr("stroke", "#d2d4d8")
.selectAll("g")
.data(function(d) {
return d3.timeDays(new Date(2018, 0, 1), new Date(2018, 3, 1));
})
.enter()
.append("g")
.attr("transform", function(d){
var x = d.getDay() * cellSize,
y = d3.timeWeek.count(d3.timeYear(d), d) * cellSize;
return "translate(" + x + "," + y + ")";
})
g.append("rect")
.attr("width", cellSize)
.attr("height", cellSize)
.attr("class", "hour bordered")
.attr("rx", 4)
.attr("ry", 4)
.datum(d3.timeFormat("%Y-%m-%d"));
g.append("text")
.text(function(d){
return d.getDate();
})
.attr("y", cellSize)
.style("font-family", "arial")
.style("font-size", "8pt")
svg.append("g")
.attr("fill", "none")
.attr("stroke", "#000")
.selectAll("path")
.data(function(d) {
return d3.timeMonths(new Date(2018, 0, 1), new Date(2018, 3, 1));
})
.enter().append("path")
.attr("d", pathMonth);
d3.csv("static/test.csv", function(error, csv) {
if (error) throw error;
var data = d3.nest()
.key(function(d) {
return d.Date;
})
.rollup(function(d) {
return (d[0].Close - d[0].Open) / d[0].Open;
})
.object(csv);
rect.filter(function(d) {
return d in data;
})
.attr("fill", function(d) {
return color(data[d]);
})
.append("title")
.text(function(d) {
return d + ": " + formatPercent(data[d]);
});
});
function pathMonth(t0) {
var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
d0 = t0.getDay(),
w0 = d3.timeWeek.count(d3.timeYear(t0), t0),
d1 = t1.getDay(),
w1 = d3.timeWeek.count(d3.timeYear(t1), t1);
return "M" + d0 * cellSize + "," + (w0) * cellSize + "H" + 7 * cellSize + "V" + (w1) * cellSize + "H" + (d1 + 1) * cellSize + "V" + (w1 + 1) * cellSize + "H" + 0 + "V" + (w0 + 1) * cellSize + "H" + d0 * cellSize + "Z";
}
var start_box = svg.append("rect")
.attr("x", 225)
.attr("y", 45)
.attr("width", cellSize)
.attr("height", cellSize)
.attr("rx", 4)
.attr("ry", 4)
.attr("class", "hour bordered")
.style("fill", "#FFD700");
</script>
</body>
</html>
My problem is labels of donut chart too long. It'll be cut lost when it get over width or height of svg.
i don't know how i must cut it to 2 or more line. I try to add tag div outside tag text but it's wrong. Who can give me a solution. This is my code:
var tooltip = d3.select('#chart')
.append('div')
.attr('class', 'tooltips');
tooltip.append('div')
.attr('class', 'label');
var data = [
{country: "UNITED KINGDOMhhhhhhhhhhhhhhhhhhhhhhhhh hhhhhhhhhhhhhhhhh", val: 86.68},
{country: "HONG KONGggggggggggggggggggggg g g g gg g g g g gg gg g g ", val: 9.23},
{country: "OTHERS", val: 4.09}
];
var w = 600,
h = 600,
r = Math.min(w, h) / 2 - 100,
labelr = r + 30, // radius for label anchor
color = d3.scale.category20(),
donut = d3.layout.pie(),
arc = d3.svg.arc().innerRadius(r * .6).outerRadius(r);
var vis = d3.select("#chart")
.append("svg:svg")
.data([data])
.attr("width", w + 150)
.attr("height", h);
var arcs = vis.selectAll("g.arc")
.data(donut.value(function(d) { return d.val }))
.enter().append("svg:g")
.attr("class", "arc")
.attr("transform", "translate(" + (r + 200) + "," + (r+100) + ")");
var arcOver = d3.svg.arc()
.innerRadius(r * .57)
.outerRadius(r + 5);
arcs.append("path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc)
.on("mouseover",function(d){
d3.select(this).transition()
.duration(50)
.attr("d", arcOver);
tooltip.select('.label').html(d.value + "%");
tooltip.style('display', 'block');
})
.on('mouseout', function() {
d3.select(this).transition()
.duration(50)
.attr("d", arc);
tooltip.style('display', 'none');
})
.on('mousemove', function(d) {
tooltip.style('top', (d3.event.pageY - 80) + 'px')
.style('left', (d3.event.pageX + 10) + 'px');
});
arcs.append("text")
.attr("transform", function(d) {
var c = arc.centroid(d),
x = c[0],
y = c[1],
// pythagorean theorem for hypotenuse
h = Math.sqrt(x*x + y*y);
return "translate(" + (x/h * labelr) + ',' +
(y/h * labelr) + ")";
})
.attr("dy", ".35em")
.attr("text-anchor", function(d) {
// are we past the center?
return (d.endAngle + d.startAngle)/2 > Math.PI ?
"end" : "start";
})
.text(function(d) { return d.data.country; });
Thanks!!!
var tooltip = d3.select('#chart')
.append('div')
.attr('class', 'tooltips');
tooltip.append('div')
.attr('class', 'label');
var data = [
{country: "UNITED KINGDOMhhhhhhhhhhhhhhhhhhhhhhhhh hhhhhhhhhhhhhhhhh", val: 86.68},
{country: "HONG KONGggggggggggggggggggggg g g g gg g g g g gg gg g g ", val: 9.23},
{country: "OTHERS", val: 4.09}
];
var w = 600,
h = 600,
r = Math.min(w, h) / 2 - 100,
labelr = r + 30, // radius for label anchor
color = d3.scale.category20(),
donut = d3.layout.pie(),
arc = d3.svg.arc().innerRadius(r * .6).outerRadius(r);
var vis = d3.select("#chart")
.append("svg:svg")
.data([data])
.attr("width", w + 150)
.attr("height", h);
var arcs = vis.selectAll("g.arc")
.data(donut.value(function(d) { return d.val }))
.enter().append("svg:g")
.attr("class", "arc")
.attr("transform", "translate(" + (r + 200) + "," + (r+100) + ")");
var arcOver = d3.svg.arc()
.innerRadius(r * .57)
.outerRadius(r + 5);
arcs.append("path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc)
.on("mouseover",function(d){
d3.select(this).transition()
.duration(50)
.attr("d", arcOver);
tooltip.select('.label').html(d.value + "%");
tooltip.style('display', 'block');
})
.on('mouseout', function() {
d3.select(this).transition()
.duration(50)
.attr("d", arc);
tooltip.style('display', 'none');
})
.on('mousemove', function(d) {
tooltip.style('top', (d3.event.pageY - 80) + 'px')
.style('left', (d3.event.pageX + 10) + 'px');
});
var text = arcs.append("text")
.attr("transform", function(d) {
var c = arc.centroid(d),
x = c[0],
y = c[1],
// pythagorean theorem for hypotenuse
h = Math.sqrt(x*x + y*y);
return "translate(" + (x/h * labelr) + ',' +
(y/h * labelr) + ")";
})
.attr("dy", ".35em")
.attr("text-anchor", function(d) {
// are we past the center?
return (d.endAngle + d.startAngle)/2 > Math.PI ?
"end" : "start";
});/*
.text(function(d) {
return d.data.country;
});*/
text.each(function(d){
var text = d3.select(this),
words = d.data.country.split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 0.22, // ems
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null)
.append("tspan")
.attr("x", 0)
.attr("y", y)
.attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > 10) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan")
.attr("x", 0)
.attr("y", y)
.attr("dy", ++lineNumber * lineHeight + dy + "em")
.text(word);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id='chart'></div>
After doing a great lot of work out. I got this.
Hope this will fulfill your need/requirement.
All I did is,
Adding tspan elements to text element.Observe below code. text is a var see above code. which holds all text elements which we want to add to the every g
text.each(function(d){
var text = d3.select(this),//selecting current text element
words = d.data.country.split(/\s+/).reverse(),//splitting the country name by using space, if you want you can change.
word,//to store one one word
line = [],
lineNumber = 0,
lineHeight = 0.22, // ems, you can increase for more gaps vise versa
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null)
.append("tspan")
.attr("x", 0)
.attr("y", y)
.attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > 10) {//here I'm checking the length of the text
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan")
.attr("x", 0)
.attr("y", y)
.attr("dy", ++lineNumber * lineHeight + dy + "em")//setting the gap between the label line gaps.
.text(word);
}
}
})