<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Testing Pie Chart</title>
<script src="d3.v3.min.js" charset="utf-8"></script>
<style type="text/css">
#chart {
margin-top: 100px;
position: absolute;
margin-right: 50px;
margin-left: 50px;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #900C3F;
display: inline-block;
font-size: 12px;
left: 600px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
width: 150px;
z-index: 10;
opacity: 1;
}
rect {
stroke-width: 2;
}
path {
stroke: #ffffff;
stroke-width: 0.5;
}
div.tooltip {
position: absolute;
z-index: 999;
padding: 10px;
background: #f4f4f4;
border: 0px;
border-radius: 3px;
pointer-events: none;
font-size: 11px;
color: #000;
line-height: 16px;
border: 1px solid #d4d4d4;
}
.legend{
margin-left: 300px;
}
</style>
</head>
<body>
<div id="chart"></div>
<div id="toolTip" class="tooltip" style="opacity: 0;"></div>
<script type="text/javascript">
var div = d3.select("#toolTip");
var data = [ ["IP", "count"]
["192.168.12.1", "20"],
["76.09.45.34", "40"],
["34.91.23.76", "80"],
["192.168.19.32", "16"],
["192.168.10.89", "50"],
["192.178.34.07", "18"],
["192.168.12.98", "30"]];
var width = 300,
height = 300;
var margin = {top: 15, right: 15, bottom: 20, left: 40},
radius = Math.min(width, height) / 2 - 10;
var legendRectSize = 18,
legendSpacing = 4;
var color = d3.scale.category20b();
var arc = d3.svg.arc()
.outerRadius(radius);
var arcOver = d3.svg.arc()
.outerRadius(radius + 10);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.data.count; });
var labelArc = d3.svg.arc()
.outerRadius(radius - 40)
.innerRadius(radius - 40);
var svg = d3.select("#chart").append("svg")
.datum(data)
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var arcs = svg.selectAll(".arc")
.data(pie)
.enter().append("g")
.attr("class", "arc");
var arcs2 = svg.selectAll(".arc2")
.data(pie)
.enter().append("g")
.attr("class", "arc2");
arcs.append("path")
.attr("fill", function(d, i) { return color(i); })
.on("mouseover", function(d) {
var htmlMsg="";
div.transition()
.style("opacity",0.9);
var total = d3.sum(data.map(function(d) {
return d.count;
}));
var percent = Math.round(1000 * d.data.count / total) / 10;
div.html(
"IP :"+ d.data.IP +""+"<br/>"+
"Count : " + d.data.count +"<br/>" +
"Percent: " + percent + '%'+ htmlMsg)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY) + "px");
svg.selectAll("path").sort(function (a, b) {
if (a != d) return -1;
else return 1;
});
var endAngle = d.endAngle + 0.1;
var startAngle = d.startAngle - 0.1;
var arcOver = d3.svg.arc()
.outerRadius(radius + 10).endAngle(endAngle).startAngle(startAngle);
d3.select(this)
.attr("stroke","white")
.transition()
.ease("bounce")
.duration(1000)
.attr("d", arcOver)
.attr("stroke-width",6);
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
d3.select(this).transition()
.attr("d", arc)
.attr("stroke","none");
})
.transition()
.ease("bounce")
.duration(2000)
.attrTween("d", tweenPie);
function tweenPie(b) {
b.innerRadius = 0;
var i = d3.interpolate({startAngle: 0, endAngle: 0}, b);
return function(t) { return arc(i(t)); };
}
var k=0;
arcs2.append("text")
.transition()
.ease("elastic")
.duration(2000)
.delay(function (d, i) {
return i * 250;
})
.attr("x","6")
.attr("dy", ".35em")
.text(function(d) { if(d.data.count >0){ k = k+1; return d.data.count;} })
.attr("transform", function(d) { if (k >1){return "translate(" + labelArc.centroid(d) + ") rotate(" + angle(d) + ")";} else{return "rotate(-360)";} })
.attr("font-size", "10px");
function type(d) {
d.count = +d.count;
return d;
}
function angle(d) {
var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
return a > 90 ? a - 180 : a;
}
var legend = d3.select("#chart")
.append("svg")
.attr("class", "legend")
.attr("width", radius+50)
.attr("height", radius * 2)
.selectAll("g")
.data(color.domain())
.enter()
.append("g")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append('rect')
.attr('width', legendRectSize)
.attr('height', legendRectSize)
.style('fill', color)
.style('stroke', color);
legend.append('text')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.data(data)
.text(function(d,i) { return d.IP; });
</script>
</body>
</html>
I am trying to make a pie chart with the provided dataset and I am facing error. How to define the parameter d to fetch the data from the variable "data" and its subsequent values "IP" and "count"? I dont know what mistake I am doing in my codes. What should I change in my current codes so that I can get a pie chart with current data format? Please help me. I am stuck. The condition is I should not use any kind of .csv or .tsv file in this code for importing. Thanks for any help.
One issue is with your data array... you need to remove the first item in it [ Also, you are missing a ',' after the item. but the item is itself not required as its an array ].
Second is with d.data.count inside the pie function... you need to refer it as d[1] as you need to plot the second item in data array in your chart.
Working code below:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Testing Pie Chart</title>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<style type="text/css">
#chart {
margin-top: 100px;
position: absolute;
margin-right: 50px;
margin-left: 50px;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #900C3F;
display: inline-block;
font-size: 12px;
left: 600px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
width: 150px;
z-index: 10;
opacity: 1;
}
rect {
stroke-width: 2;
}
path {
stroke: #ffffff;
stroke-width: 0.5;
}
div.tooltip {
position: absolute;
z-index: 999;
padding: 10px;
background: #f4f4f4;
border: 0px;
border-radius: 3px;
pointer-events: none;
font-size: 11px;
color: #000;
line-height: 16px;
border: 1px solid #d4d4d4;
}
.legend{
margin-left: 300px;
}
</style>
</head>
<body>
<div id="chart"></div>
<div id="toolTip" class="tooltip" style="opacity: 0;"></div>
<script type="text/javascript">
var div = d3.select("#toolTip");
var data = [
["192.168.12.1", "20"],
["76.09.45.34", "40"],
["34.91.23.76", "80"],
["192.168.19.32", "16"],
["192.168.10.89", "50"],
["192.178.34.07", "18"],
["192.168.12.98", "30"]];
var width = 300,
height = 300;
var margin = {top: 15, right: 15, bottom: 20, left: 40},
radius = Math.min(width, height) / 2 - 10;
var legendRectSize = 18,
legendSpacing = 4;
var color = d3.scale.category20b();
var arc = d3.svg.arc()
.outerRadius(radius);
var arcOver = d3.svg.arc()
.outerRadius(radius + 10);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d[1]; });
var labelArc = d3.svg.arc()
.outerRadius(radius - 40)
.innerRadius(radius - 40);
var svg = d3.select("#chart").append("svg")
.datum(data)
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var arcs = svg.selectAll(".arc")
.data(pie)
.enter().append("g")
.attr("class", "arc");
var arcs2 = svg.selectAll(".arc2")
.data(pie)
.enter().append("g")
.attr("class", "arc2");
arcs.append("path")
.attr("fill", function(d, i) { return color(i); })
.on("mouseover", function(d) {
var htmlMsg="";
div.transition()
.style("opacity",0.9);
var total = d3.sum(data.map(function(d) {
return d.count;
}));
var percent = Math.round(1000 * d.data.count / total) / 10;
div.html(
"IP :"+ d.data.IP +""+"<br/>"+
"Count : " + d.data.count +"<br/>" +
"Percent: " + percent + '%'+ htmlMsg)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY) + "px");
svg.selectAll("path").sort(function (a, b) {
if (a != d) return -1;
else return 1;
});
var endAngle = d.endAngle + 0.1;
var startAngle = d.startAngle - 0.1;
var arcOver = d3.svg.arc()
.outerRadius(radius + 10).endAngle(endAngle).startAngle(startAngle);
d3.select(this)
.attr("stroke","white")
.transition()
.ease("bounce")
.duration(1000)
.attr("d", arcOver)
.attr("stroke-width",6);
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
d3.select(this).transition()
.attr("d", arc)
.attr("stroke","none");
})
.transition()
.ease("bounce")
.duration(2000)
.attrTween("d", tweenPie);
function tweenPie(b) {
b.innerRadius = 0;
var i = d3.interpolate({startAngle: 0, endAngle: 0}, b);
return function(t) { return arc(i(t)); };
}
var k=0;
arcs2.append("text")
.transition()
.ease("elastic")
.duration(2000)
.delay(function (d, i) {
return i * 250;
})
.attr("x","6")
.attr("dy", ".35em")
.text(function(d) { if(d.data.count >0){ k = k+1; return d.data.count;} })
.attr("transform", function(d) { if (k >1){return "translate(" + labelArc.centroid(d) + ") rotate(" + angle(d) + ")";} else{return "rotate(-360)";} })
.attr("font-size", "10px");
function type(d) {
d.count = +d.count;
return d;
}
function angle(d) {
var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
return a > 90 ? a - 180 : a;
}
var legend = d3.select("#chart")
.append("svg")
.attr("class", "legend")
.attr("width", radius+50)
.attr("height", radius * 2)
.selectAll("g")
.data(color.domain())
.enter()
.append("g")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append('rect')
.attr('width', legendRectSize)
.attr('height', legendRectSize)
.style('fill', color)
.style('stroke', color);
legend.append('text')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.data(data)
.text(function(d,i) { return d.IP; });
</script>
</body>
</html>
Your data input format is wrong.
Change from:
var data = [ ["IP", "count"]
["192.168.12.1", "20"],
["76.09.45.34", "40"],
["34.91.23.76", "80"],
["192.168.19.32", "16"],
["192.168.10.89", "50"],
["192.178.34.07", "18"],
["192.168.12.98", "30"]];
to
var data = [
{"IP":"192.168.12.1", "count":"20"},
{"IP":"76.09.45.34", "count":"40"},
{"IP":"34.91.23.76", "count":"80"},
{"IP":"192.168.19.32", "count":"16"},
{"IP":"192.168.10.89", "count":"50"},
{"IP":"192.178.34.07", "count":"18"},
{"IP":"192.168.12.98", "count":"30"}
];
Related
I want to create a dynamic .container where each circle preserves its size ratio and always distributes to fit the available space of the .container.
How do I modify the code so that the distribution of the data points always resizes to the bounds of the .container while maintaining the size ratio of each circle?
.container {
width: 400px;
height: 200px;
}
(function() {
var json = {
call_data: [
[
"Lifestyle",
1,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/5bb3ce2f801fbc657f83dd57_pp-lifestyle(white).svg"
],
[
"Sports",
2,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/5c9131911ad86f445cb5abc7_pp-sport(white).svg"
],
[
"Environment",
8,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/59f2a4bef42fff000159ba7a_pp-environ(white).svg"
],
[
"Medical",
6,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/59f2a4dc831e8500015fda53_pp-health(white).svg"
],
[
"Food",
4,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/59f8c2cc78cc2d0001fd4a7e_pp-food(white).svg"
]
]
};
var width = 200;
var height = 200;
var tooltip = d3
.select(".bubble_chart")
.append("div")
.classed("tooltip", true);
var svg = d3
.select(".bubble_chart")
.append("svg")
//responsive SVG needs these 2 attributes and no width and height attr
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", "0 0 " + width + " " + height);
var bubble = d3.layout
.pack()
.size([200, 200])
.value(function(d) {
return d.size;
})
.padding(12);
// generate data with calculated layout values
var nodes = bubble.nodes(processData(json)).filter(function(d) {
return !d.children;
}); // filter out the outer bubble
var vis = svg.selectAll("circle").data(nodes, function(d, i) {
return d.name + i;
});
vis
.enter()
.append("circle")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
.attr("class", function(d) {
return d.className;
})
.attr("r", 0)
.transition()
.duration(1000)
.attr("r", function(d) {
return d.r;
});
vis
.enter()
.append("svg:image")
.attr("transform", d => "translate(" + d.x + "," + d.y + ")")
.attr("x", d => -(d.r / 1.5) / 2)
.attr("y", d => -(d.r / 1.5) / 2)
.attr("xlink:href", function(d) {
return d.img;
})
.attr("width", d => d.r / 1.5)
.transition()
.duration(1000)
.style("opacity", 1);
/*
vis
.enter()
.append("text")
.attr("transform", d => "translate(" + d.x + "," + d.y + ")")
.attr("fill", "white")
.attr("text-anchor", "middle")
.attr("font-size", d => d.r / (d.r * 5 / 100))
.text(d => d.name);
*/
/* vis
.enter()
.append("text")
.attr("transform", d => "translate(" + d.x + "," + d.y + ")")
.attr("fill", "white")
.attr("text-anchor", "middle")
.attr("font-size", d => d.r / (d.r * 3 / 100))
.text(d => d.value);
*/
vis
.on("mousemove", function(d) {
tooltip
.style("opacity", 1)
.style("left", d3.event.x - tooltip.node().offsetWidth / 2 + "px")
.style("top", d3.event.y + 25 + "px").html(`
<p>Category: ${d.name}</p>
<p>Ordered: ${d.value}</p>
`);
})
.on("mouseout", function() {
tooltip.style("opacity", 0);
});
function processData(data) {
var obj = data.call_data;
var newDataSet = [];
for (var prop in obj) {
newDataSet.push({
name: obj[prop][0],
className: obj[prop][0].toLowerCase(),
size: obj[prop][1],
img: obj[prop][2]
});
}
return {
children: newDataSet
};
}
var aspect = width / height,
chart = d3.select('.bubble_chart');
d3.select(window)
.on("resize", function() {
var targetWidth = chart.node().getBoundingClientRect().width;
chart.attr("width", targetWidth);
chart.attr("height", targetWidth / aspect);
});
})();
.container {
border: 2px solid red;
width: 400px;
height: 200px;
}
.bubble_chart {
flex: 1;
border: 2px solid
}
.lifestyle {
fill: #89BED3;
}
.sports {
fill: #2A83D4;
}
.environment {
fill: #6CC070;
}
.food {
fill: #665C9E;
}
.medical {
fill: #C13E40;
}
.tooltip {
opacity: 0;
position: absolute;
pointer-events: none;
background-color: #fafafa;
border-radius: 8px;
padding: 15px;
z-index: 999;
box-shadow: 1px 1px 3px 0 rgba(0, 0, 0, .1)
}
.tooltip p {
margin: 0;
}
.tooltip:before {
content: " ";
position: absolute;
border: 12px solid transparent;
border-bottom-color: #fafafa;
top: -20px;
left: 50%;
margin-left: -12px;
}
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.5/d3.js"></script>
<div class="container">
<div class="bubble_chart"></div>
</div>
You should set your width and height to the bounding rect height and width at the outset. Right now you have it set as both 200px, which are the same.
Do that like this:
var width = document.querySelector(".container").getBoundingClientRect().width;
var height = document.querySelector(".container").getBoundingClientRect().height;
(function() {
var json = {
call_data: [
[
"Lifestyle",
1,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/5bb3ce2f801fbc657f83dd57_pp-lifestyle(white).svg"
],
[
"Sports",
2,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/5c9131911ad86f445cb5abc7_pp-sport(white).svg"
],
[
"Environment",
8,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/59f2a4bef42fff000159ba7a_pp-environ(white).svg"
],
[
"Medical",
6,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/59f2a4dc831e8500015fda53_pp-health(white).svg"
],
[
"Food",
4,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/59f8c2cc78cc2d0001fd4a7e_pp-food(white).svg"
]
]
};
var width = document.querySelector(".container").getBoundingClientRect().width;
var height = document.querySelector(".container").getBoundingClientRect().height;
var tooltip = d3
.select(".bubble_chart")
.append("div")
.classed("tooltip", true);
var svg = d3
.select(".bubble_chart")
.append("svg")
//responsive SVG needs these 2 attributes and no width and height attr
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", "0 0 " + width + " " + height);
var bubble = d3.layout
.pack()
.size([200, 200])
.value(function(d) {
return d.size;
})
.padding(12);
// generate data with calculated layout values
var nodes = bubble.nodes(processData(json)).filter(function(d) {
return !d.children;
}); // filter out the outer bubble
var vis = svg.selectAll("circle").data(nodes, function(d, i) {
return d.name + i;
});
vis
.enter()
.append("circle")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
.attr("class", function(d) {
return d.className;
})
.attr("r", 0)
.transition()
.duration(1000)
.attr("r", function(d) {
return d.r;
});
vis
.enter()
.append("svg:image")
.attr("transform", d => "translate(" + d.x + "," + d.y + ")")
.attr("x", d => -(d.r / 1.5) / 2)
.attr("y", d => -(d.r / 1.5) / 2)
.attr("xlink:href", function(d) {
return d.img;
})
.attr("width", d => d.r / 1.5)
.transition()
.duration(1000)
.style("opacity", 1);
/*
vis
.enter()
.append("text")
.attr("transform", d => "translate(" + d.x + "," + d.y + ")")
.attr("fill", "white")
.attr("text-anchor", "middle")
.attr("font-size", d => d.r / (d.r * 5 / 100))
.text(d => d.name);
*/
/* vis
.enter()
.append("text")
.attr("transform", d => "translate(" + d.x + "," + d.y + ")")
.attr("fill", "white")
.attr("text-anchor", "middle")
.attr("font-size", d => d.r / (d.r * 3 / 100))
.text(d => d.value);
*/
vis
.on("mousemove", function(d) {
tooltip
.style("opacity", 1)
.style("left", d3.event.x - tooltip.node().offsetWidth / 2 + "px")
.style("top", d3.event.y + 25 + "px").html(`
<p>Category: ${d.name}</p>
<p>Ordered: ${d.value}</p>
`);
})
.on("mouseout", function() {
tooltip.style("opacity", 0);
});
function processData(data) {
var obj = data.call_data;
var newDataSet = [];
for (var prop in obj) {
newDataSet.push({
name: obj[prop][0],
className: obj[prop][0].toLowerCase(),
size: obj[prop][1],
img: obj[prop][2]
});
}
return {
children: newDataSet
};
}
var aspect = width / height,
chart = d3.select('.bubble_chart');
d3.select(window)
.on("resize", function() {
var targetWidth = chart.node().getBoundingClientRect().width;
chart.attr("width", targetWidth);
chart.attr("height", targetWidth / aspect);
});
})();
.container {
border: 2px solid red;
width: 400px;
height: 200px;
}
.bubble_chart {
flex: 1;
border: 2px solid
}
.lifestyle {
fill: #89BED3;
}
.sports {
fill: #2A83D4;
}
.environment {
fill: #6CC070;
}
.food {
fill: #665C9E;
}
.medical {
fill: #C13E40;
}
.tooltip {
opacity: 0;
position: absolute;
pointer-events: none;
background-color: #fafafa;
border-radius: 8px;
padding: 15px;
z-index: 999;
box-shadow: 1px 1px 3px 0 rgba(0, 0, 0, .1)
}
.tooltip p {
margin: 0;
}
.tooltip:before {
content: " ";
position: absolute;
border: 12px solid transparent;
border-bottom-color: #fafafa;
top: -20px;
left: 50%;
margin-left: -12px;
}
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.5/d3.js"></script>
<div class="container">
<div class="bubble_chart"></div>
</div>
I've a d3js barchart as below. I'm adding a tooltip on click of each bar. I'm unable add event to close the tooltip which is inside the tip. Is there a way to add that?
The snippet as follows:
var margin = {
top: 10,
right: 0,
bottom: 58,
left: 30
};
var width = 300 - margin.left - margin.right;
var height = 300 - margin.top - margin.bottom;
var barWidth = 40;
var graph;
var x;
var y;
var dataset;
var yTicks = 6;
var tooltipEl = function(d) {
return (
'<div class="tip__container">' +
'<div class="val">' +
d.val +
"</div>" +
'<div class="close">' +
"<button>×</button>" +
"</div>" +
"</div>"
);
};
dataset = [{
desc: "test1",
val: 40
},
{
desc: "some dummy text here",
val: 120
}
];
x = d3
.scaleBand()
.domain(
dataset.map(function(d) {
return d.desc;
})
)
.range([0, width]);
y = d3
.scaleLinear()
.range([height, 0])
.domain([0, 350]);
graph = d3
.select("#graph")
.append("svg")
.attr("class", "bar-chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Tool Tip
const div = d3
.select("#graph")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);
graph
.append("g")
.attr("class", "x-scale")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll(".tick text")
.call(wrap, x.bandwidth());
graph
.append("g")
.attr("class", "y-scale")
.call(
d3
.axisLeft(y)
.ticks(yTicks)
.tickPadding(10)
);
graph
.append("g")
.attr("class", "graph-placeholder")
.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("class", "bar1")
.attr("height", height)
.attr("width", barWidth)
.attr("x", d => x(d.desc) + (x.bandwidth() - barWidth) / 2);
graph
.append("g")
.attr("class", "graph-main")
.selectAll("bar1")
.data(dataset)
.enter()
.append("rect")
.attr("class", "bar2")
.attr("x", d => x(d.desc) + (x.bandwidth() - barWidth) / 2)
.attr("y", function(d) {
return y(d.val);
})
.attr("height", function(d) {
return height - y(d.val);
})
.attr("width", barWidth)
.on("click", d => {
div.html(tooltipEl(d));
div
.transition()
.duration(200)
.style("display", "block")
.style("opacity", 1);
div
.style("left", x(d.desc) + x.bandwidth() / 2 - 1 + "px")
.style("top", height + margin.top + 10 + "px");
});
graph
.append("g")
.attr("class", "bar-label")
.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(d => d.val + "%")
.attr("y", function(d) {
return y(d.val) - 5;
})
.attr("x", function(d) {
return x(d.desc) + x.bandwidth() / 2;
});
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text
.text()
.split(/\s+/)
.reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1,
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() > width) {
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);
}
}
});
}
.bar-chart {
background-color: #ccc;
}
.bar2 {
fill: steelblue;
}
.bar1 {
fill: #f2f2f2;
}
text {
font-size: 12px;
text-anchor: middle;
}
.bar-label text {
text-anchor: middle;
}
path.domain {
stroke-width: 0;
display: none;
}
.tooltip {
background: #FFFFFF;
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.33);
font-family: "Segoe UI";
line-height: normal;
padding: 15px;
width: 100px;
position: absolute;
display: none;
}
.tooltip__container {
display: flex;
}
.tooltip::before {
content: "";
position: absolute;
left: 22px;
top: -8px;
transition: all 0.5s ease;
border: 8px solid #fff;
box-shadow: -5px -5px 5px rgba(0, 0, 0, 0.1);
transform: rotate(45deg);
}
.tip__container {
display: flex;
justify-content: space-between;
}
.close {
margin-left: 20px;
}
button {
border: 1px solid #ccc;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div class="container">
<div id="graph"></div>
</div>
Fiddle
Because your div's HTML is created by the selection.html() method inside the callback of the click function for the bars, you have to set the listener inside the same callback:
div.select("button").on("click", function() {
div.style("opacity", 0)
});
Here is your code with that change:
var margin = {
top: 10,
right: 0,
bottom: 58,
left: 30
};
var width = 300 - margin.left - margin.right;
var height = 300 - margin.top - margin.bottom;
var barWidth = 40;
var graph;
var x;
var y;
var dataset;
var yTicks = 6;
var tooltipEl = function(d) {
return (
'<div class="tip__container">' +
'<div class="val">' +
d.val +
"</div>" +
'<div class="close">' +
"<button>×</button>" +
"</div>" +
"</div>"
);
};
dataset = [{
desc: "test1",
val: 40
},
{
desc: "some dummy text here",
val: 120
}
];
x = d3
.scaleBand()
.domain(
dataset.map(function(d) {
return d.desc;
})
)
.range([0, width]);
y = d3
.scaleLinear()
.range([height, 0])
.domain([0, 350]);
graph = d3
.select("#graph")
.append("svg")
.attr("class", "bar-chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Tool Tip
const div = d3
.select("#graph")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);
graph
.append("g")
.attr("class", "x-scale")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll(".tick text")
.call(wrap, x.bandwidth());
graph
.append("g")
.attr("class", "y-scale")
.call(
d3
.axisLeft(y)
.ticks(yTicks)
.tickPadding(10)
);
graph
.append("g")
.attr("class", "graph-placeholder")
.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("class", "bar1")
.attr("height", height)
.attr("width", barWidth)
.attr("x", d => x(d.desc) + (x.bandwidth() - barWidth) / 2);
graph
.append("g")
.attr("class", "graph-main")
.selectAll("bar1")
.data(dataset)
.enter()
.append("rect")
.attr("class", "bar2")
.attr("x", d => x(d.desc) + (x.bandwidth() - barWidth) / 2)
.attr("y", function(d) {
return y(d.val);
})
.attr("height", function(d) {
return height - y(d.val);
})
.attr("width", barWidth)
.on("click", d => {
div.html(tooltipEl(d));
div.select("button").on("click", function() {
div.style("opacity", 0)
});
div
.transition()
.duration(200)
.style("display", "block")
.style("opacity", 1);
div
.style("left", x(d.desc) + x.bandwidth() / 2 - 1 + "px")
.style("top", height + margin.top + 10 + "px");
});
graph
.append("g")
.attr("class", "bar-label")
.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(d => d.val + "%")
.attr("y", function(d) {
return y(d.val) - 5;
})
.attr("x", function(d) {
return x(d.desc) + x.bandwidth() / 2;
});
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text
.text()
.split(/\s+/)
.reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1,
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() > width) {
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);
}
}
});
}
.bar-chart {
background-color: #ccc;
}
.bar2 {
fill: steelblue;
}
.bar1 {
fill: #f2f2f2;
}
text {
font-size: 12px;
text-anchor: middle;
}
.bar-label text {
text-anchor: middle;
}
path.domain {
stroke-width: 0;
display: none;
}
.tooltip {
background: #FFFFFF;
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.33);
font-family: "Segoe UI";
line-height: normal;
padding: 15px;
width: 100px;
position: absolute;
display: none;
}
.tooltip__container {
display: flex;
}
.tooltip::before {
content: "";
position: absolute;
left: 22px;
top: -8px;
transition: all 0.5s ease;
border: 8px solid #fff;
box-shadow: -5px -5px 5px rgba(0, 0, 0, 0.1);
transform: rotate(45deg);
}
.tip__container {
display: flex;
justify-content: space-between;
}
.close {
margin-left: 20px;
}
button {
border: 1px solid #ccc;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div class="container">
<div id="graph"></div>
</div>
I'm trying to expand the outerRadius of an arc thats created in my piechart. I fail to see how to do this upon mouse over. I have tried to make a new arc with a bigger outerRadius that I have made earlier (bArc), and apply this to my path attribute "d"
d3.select(this).select("path").attr("d", bArc);
in an mouseover event on path
path.on("mouseover", function(d){
but to no avail, and no errors in the console. I'm a bit at a loss, and all resources I can find on the subject seems to be old and deprecated for v4.
I have made this fiddle:
https://jsfiddle.net/sw8h0uvj/
This line...
d3.select(this).select("svg").attr("d", bArc);
... makes little sense. You have to apply the changes to the DOM element, which is simply this. Therefore, it should be:
d3.select(this).attr("d", bArc);
Don't forget to change the d attribute back when you do mouseout.
Here is your code with those changes:
var data = [{
label: '0-24%',
color: "#ff875e",
highlight: "#ff7a4d",
value: 3,
},
{
label: '25%-49%',
color: "#f6bc58",
highlight: "#f5b13d",
value: 1,
},
{
label: '50%-74%',
color: "#eae860",
highlight: "#e7e54b",
value: 2,
},
{
label: '75%-100%',
color: "#85d280",
highlight: "#80d07b",
value: 3,
}
];
var tooltip = d3.select('body')
.append('div')
.attr('class', 'tooltip2')
.style("opacity", 0);
var width = 360;
var height = 360;
var radius = Math.min(width, height) / 2.5;
var outerRadius = height / 2 - 20;
//D3 allows colours to be defined as a range, beneath is input the ranges in same order as our data set above. /Nicklas
var color = d3.scaleOrdinal()
.range(['#ff875e', '#f6bc58', '#eae860', '#85d280']);
var svg = d3.select('#piechart2')
.append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + (width / 2) +
',' + (height / 2) + ')');
var arc = d3.arc()
.innerRadius(0)
.outerRadius(radius)
.padAngle(.05)
.padRadius(radius / 5);
var bArc = d3.arc()
.innerRadius(0)
.outerRadius(radius * 1.1)
.padAngle(.05)
.padRadius(radius / 5);
var pie = d3.pie()
.value(function(d) {
return d.value;
})
.sort(null);
var path = svg.selectAll('path')
.data(pie(data))
.enter()
.append('path')
.attr('d', arc)
.attr('fill', function(d) {
return color(d.data.color);
});
path.transition()
.duration(500)
.attrTween("d", tweenPie);
path.on("mouseover", function(d) {
tooltip.transition()
.duration(200)
.style("opacity", .9)
.style("display", null)
.text(d.data.label + ": " + d.data.value);
d3.select(this).transition()
.duration(500)
.style('fill', d.data.highlight)
.attr("d", bArc);
});
path.on("mousemove", function() {
tooltip.style("top", (event.pageY - 10) + "px").style("left", (event.pageX + 10) + "px");
});
path.on("mouseout", function(d) {
d3.select(this).transition()
.duration(500)
.style('fill', d.data.color)
.attr("d", arc);
tooltip.transition()
.duration(300)
.style("opacity", 0);
});
function tweenPie(b) {
b.innerRadius = 0;
var i = d3.interpolate({
startAngle: 0,
endAngle: 0
}, b);
return function(t) {
return arc(i(t));
};
}
.tooltip2 {
position: absolute;
text-align: center;
width: auto;
height: 28px;
padding: 2px;
font: 18px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<div id="piechart2" style="text-align:center; margin-bottom:1em;">
</div>
I've got this d3js v3 chart and was wondering if it's possible to append the values in a text format to both the bar and the donut chart, and if so, how you would go about doing it?
Here is the code:
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<style>
body {
font-family:arial;
font-size:10px;
margin:auto;
width:1100px;
}
.axis text {
font: 10px sans-serif;
}
.axis line,
.axis path {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
select {
background-color: #fff;
border: 1px solid #fff;
border-bottom: 1px solid #ccc;
color: #000;
padding: 3px 3px;
text-align: center;
text-decoration: none;
font-size: 10px;
margin: 2px 2px;
cursor: pointer;
}
select:focus {outline:0;}
.Row
{
display: table;
width: 100%;
table-layout: fixed;
}
.Column
{
display: table-cell;
position:relative;
}
</style>
</head>
<body>
<div class="Row">
<div class="Column" id="chart"></div>
</div>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var dispatch = d3.dispatch("load", "statechange");
var groups = [
"Team 1",
"Team 2",
"Team 3"
];
d3.csv("data.csv", type, function(error, states) {
if (error) throw error;
var stateById = d3.map();
states.forEach(function(d) { stateById.set(d.id, d); });
dispatch.load(stateById);
dispatch.statechange(stateById.get("CA"));
});
// A drop-down menu for selecting a state; uses the "menu" namespace.
dispatch.on("load.menu", function(stateById) {
var select = d3.select("#chart")
.append("div")
.append("select")
.on("change", function() { dispatch.statechange(stateById.get(this.value)); });
select.selectAll("option")
.data(stateById.values())
.enter().append("option")
.attr("value", function(d) { return d.id; })
.text(function(d) { return d.id; });
dispatch.on("statechange.menu", function(state) {
select.property("value", state.id);
});
});
// A bar chart to show total population; uses the "bar" namespace.
dispatch.on("load.bar", function(stateById) {
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 80 - margin.left - margin.right,
height = 290 - margin.top - margin.bottom;
var y = d3.scale.linear()
.domain([0, d3.max(stateById.values(), function(d) { return d.total; })])
.rangeRound([height, 0])
.nice();
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
var rect = svg.append("rect")
.attr("x", 4)
.attr("width", width - 4)
.attr("y", height)
.attr("height", 0)
.style("fill", "#aaa");
dispatch.on("statechange.bar", function(d) {
rect.transition()
.attr("y", y(d.total))
.attr("height", y(0) - y(d.total));
});
});
// A pie chart to show population by age group; uses the "pie" namespace.
dispatch.on("load.pie", function(stateById) {
var width = 260,
height = 300,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.domain(groups)
.range(["steelblue", "lightblue", "darkorange"]);
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(radius - 60);
var pie = d3.layout.pie()
.sort(null);
var svg = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var path = svg.selectAll("path")
.data(groups)
.enter().append("path")
.style("fill", color)
.each(function() { this._current = {startAngle: 0, endAngle: 0}; });
dispatch.on("statechange.pie", function(d) {
path.data(pie.value(function(g) { return d[g]; })(groups)).transition()
.attrTween("d", function(d) {
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
return arc(interpolate(t));
};
});
});
});
// Coerce population counts to numbers and compute total per state.
function type(d) {
d.total = d3.sum(groups, function(k) { return d[k] = +d[k]; });
return d;
}
</script>
</body>
</html>
And here's the dataset:
id,Team 1,Team 2,Team 3
AL,3105,5523,2590
AK,5208,8564,4215
AZ,5159,8286,3626
AR,2020,3432,1572
CA,2704,4499,2159
CO,3582,5871,2617
CT,2116,4036,1969
DE,5931,9949,4741
DC,3635,5043,2522
FL,1140,1938,9250
GA,7405,1250,5578
HI,8720,1340,6401
You have to create the label :
var label = svg.append("text")
.attr("x", 4)
.attr("y", height)
.attr("dy", ".35em")
.text(function(d) { return "0"; });
Then add a transition on this new text
label.transition()
.attr("y", y(d.total) + 5)
.text(d.total);
See https://plnkr.co/edit/wtq96BAZ3Zh1SaczjLT6?p=preview
Hello I am trying to add arctween transition to my pie chart. I am able to show the tooltips and legends in my pie chart but when I try to add arctween transition to my pie chart the tooltip is not working. How to make this possible to display both the tooltip and the arctween transition in this pie chart.
(function(d3) {
'use strict';
var margin = {top: 50, right: 50, bottom: 50, left: 50};
var width = 800 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var radius = Math.min(width, height) / 3;
var legendRectSize = 18;
var legendSpacing = 4;
var data = [
{"IP":"192.168.12.1", "count":20},
{"IP":"76.09.45.34", "count":40},
{"IP":"34.91.23.76", "count":80},
{"IP":"192.168.19.32", "count":16},
{"IP":"192.168.10.89", "count":50},
{"IP":"192.178.34.07", "count":18},
{"IP":"192.168.12.98", "count":30}];
var color = d3.scale.category10();
var svg = d3.select('#chart')
.append('svg')
.attr('width', width+margin.left+margin.right)
.attr('height', height+margin.left+margin.right)
.append('g')
.attr('transform', 'translate(' + (width / 2) + ',' + (height / 2) + ')');
var arc = d3.svg.arc()
.innerRadius(0)
.outerRadius(radius);
var arcOver = d3.svg.arc()
.innerRadius(0)
.outerRadius(radius + 5);
var pie = d3.layout.pie()
.sort(null)
.startAngle(1.1*Math.PI)
.endAngle(3.1*Math.PI)
.value(function(d) { return d.count; });
var tooltip = d3.select('#chart')
.append('div')
.attr('class', 'tooltip');
tooltip.append('div')
.attr('class', 'label');
tooltip.append('div')
.attr('class', 'count');
tooltip.append('div')
.attr('class', 'percent');
var path = svg.selectAll('path')
.data(pie(data))
.enter()
.append('path')
.attr('d', arc)
.attr('fill', function(d,i) {
return color(d.data.IP);
});
path.on('mouseover', function(d) {
d3.select(this).transition()
.ease("exp")
.duration(3000)
.attrTween("d", tweenPie)
.duration(200)
.attr("d", arcOver)
.style('opacity',0.7)
function tweenPie(b) {
var i = d3.interpolate({startAngle: 1.1*Math.PI, endAngle: 1.1*Math.PI}, b);
return function(t) { return arc(i(t)); };
}
var total = d3.sum(data.map(function(d) {
return d.count;
}));
var percent = Math.round(1000 * d.data.count / total) / 10;
tooltip.select('.label').html(d.data.IP);
tooltip.select('.count').html(d.data.count);
tooltip.select('.percent').html(percent + '%');
tooltip.style('display', 'block');
});
path.on("mouseout", function(d) {
d3.select(this).transition()
.duration(100)
.attr("d", arc)
.style('opacity','1');
tooltip.style('display', 'none');
});
var legend = d3.select("#chart")
.append("svg")
.attr("class", "legend")
.attr("width", radius+50)
.attr("height", radius * 2)
.selectAll("g")
.data(color.domain())
.enter()
.append("g")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append('rect')
.attr('width', legendRectSize)
.attr('height', legendRectSize)
.style('fill', color)
.style('stroke', color);
legend.append('text')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.text(function(d) { return d; });
})(window.d3);
#chart {
margin-top: 100px;
position: absolute;
margin-right: 50px;
margin-left: 50px;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #900C3F;
display: inline-block;
font-size: 12px;
left: 600px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
width: 100px;
z-index: 10;
opacity: 1;
}
rect {
stroke-width: 2;
}
path {
stroke: #ffffff;
stroke-width: 0.5;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Testing Pie Chart</title>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
<div id="chart"></div>
</body>
</html>
Please help me. Above mentioned are the codes that I have tried yet.
Thanks for help in advance.
You want something like this(http://jsbin.com/guqozu/edit?html,js,output):
.on("mouseover", function(d) {
var htmlMsg="";
div.transition()
.style("opacity", .9);
div.html(
"IP :"+d.data.IP+""+"<br/>"+
"Count : " + d.data.count +"<br/>" + htmlMsg)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY) + "px");
svg.selectAll("path").sort(function (a, b) {
if (a != d) return -1;
else return 1;
});
var endAngle = d.endAngle + 0.1;
var arcOver = d3.svg.arc()
.outerRadius(radius +10).endAngle(endAngle).startAngle(startAngle);
d3.select(this)
.attr("stroke","white")
.transition()
.ease("bounce")
.duration(1000)
.attr("d", arcOver)
.attr("stroke-width",6);
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
d3.select(this).transition()
.attr("d", arc)
.attr("stroke","none");
})
.transition()
.ease("bounce")
.duration(2000)
.attrTween("d", tweenPie);
var div = d3.select("#toolTip");
var data = [
{"IP":"192.168.12.1", "count":20},
{"IP":"76.09.45.34", "count":40},
{"IP":"34.91.23.76", "count":80},
{"IP":"192.168.19.32", "count":16},
{"IP":"192.168.10.89", "count":50},
{"IP":"192.178.34.07", "count":18},
{"IP":"192.168.12.98", "count":30}];
var width = 300,
height = 300;
var margin = {top: 15, right: 15, bottom: 20, left: 40},
radius = Math.min(width, height) / 2 - 10;
var legendRectSize = 18,
legendSpacing = 4;
var color = d3.scale.category20b();
var arc = d3.svg.arc()
.outerRadius(radius);
var arcOver = d3.svg.arc()
.outerRadius(radius + 10);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.count; });
var labelArc = d3.svg.arc()
.outerRadius(radius - 40)
.innerRadius(radius - 40);
var svg = d3.select("#chart").append("svg")
.datum(data)
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var arcs = svg.selectAll(".arc")
.data(pie)
.enter().append("g")
.attr("class", "arc");
var arcs2 = svg.selectAll(".arc2")
.data(pie)
.enter().append("g")
.attr("class", "arc2");
arcs.append("path")
.attr("fill", function(d, i) { return color(i); })
.on("mouseover", function(d) {
var htmlMsg="";
div.transition()
.style("opacity",0.9);
div.html(
"IP :"+d.data.IP+""+"<br/>"+
"Count : " + d.data.count +"<br/>" + htmlMsg)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY) + "px");
svg.selectAll("path").sort(function (a, b) {
if (a != d) return -1;
else return 1;
});
var endAngle = d.endAngle + 0.1;
var startAngle = d.startAngle - 0.1;
var arcOver = d3.svg.arc()
.outerRadius(radius + 10).endAngle(endAngle).startAngle(startAngle);
d3.select(this)
.attr("stroke","white")
.transition()
.ease("bounce")
.duration(1000)
.attr("d", arcOver)
.attr("stroke-width",6);
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
d3.select(this).transition()
.attr("d", arc)
.attr("stroke","none");
})
.transition()
.ease("bounce")
.duration(2000)
.attrTween("d", tweenPie);
function tweenPie(b) {
b.innerRadius = 0;
var i = d3.interpolate({startAngle: 0, endAngle: 0}, b);
return function(t) { return arc(i(t)); };
}
var k=0;
arcs2.append("text")
.transition()
.ease("elastic")
.duration(2000)
.delay(function (d, i) {
return i * 250;
})
.attr("x","6")
.attr("dy", ".35em")
.text(function(d) { if(d.data.count >0){ k = k+1; return d.data.count;} })
.attr("transform", function(d) { if (k >1){return "translate(" + labelArc.centroid(d) + ") rotate(" + angle(d) + ")";} else{return "rotate(-360)";} })
.attr("font-size", "10px");
function type(d) {
d.count = +d.count;
return d;
}
function angle(d) {
var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
return a > 90 ? a - 180 : a;
}
var legend = d3.select("#chart")
.append("svg")
.attr("class", "legend")
.attr("width", radius+50)
.attr("height", radius * 2)
.selectAll("g")
.data(color.domain())
.enter()
.append("g")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append('rect')
.attr('width', legendRectSize)
.attr('height', legendRectSize)
.style('fill', color)
.style('stroke', color);
legend.append('text')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.data(data)
.text(function(d,i) { return d.IP; });
#chart {
margin-top: 100px;
position: absolute;
margin-right: 50px;
margin-left: 50px;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #900C3F;
display: inline-block;
font-size: 12px;
left: 600px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
width: 150px;
z-index: 10;
opacity: 1;
}
rect {
stroke-width: 2;
}
path {
stroke: #ffffff;
stroke-width: 0.5;
}
div.tooltip {
position: absolute;
z-index: 999;
padding: 10px;
background: #f4f4f4;
border: 0px;
border-radius: 3px;
pointer-events: none;
font-size: 11px;
color: #000;
line-height: 16px;
border: 1px solid #d4d4d4;
}
.legend{
margin-left: 300px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Testing Pie Chart</title>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
<div id="chart"></div>
<div id="toolTip" class="tooltip" style="opacity: 0;"></div>
<script type="text/javascript">
</script>
</body>
</html>
Thank you SiddP for suggesting some useful tips. Based on his codes and my research I have added a legend along with arctween and tooltip to this pie chart to make it complete. I hope this helps someone struggling over D3 pie chart.
Thank you stackoverflow. :}