Related
I have a bunch of charts which get drawn in the same div by the user clicking on a link (each click removes the previous svg and then draws the new one). All charts are positioned in the center of the div as expected except donut charts. Any reasons why? I've created a JS Fiddle to help illustrate this.
JS Fiddle
Basically, I have three functions. The generic drawChart() function which takes in the index of the button which has been clicked and contains a switch statement which picks what chart to draw. Then there is chartTwo() which is just two lines to illustrate how that chart is positioned in the center. chartOne() is a donut chart which is being positioned outside of top left corner.
Thanks for any help.
Generic chart builder func
function drawChart(int){
var $chartarea = $('#chartarea'),
ca_w = $chartarea.innerWidth(),
ca_h = $chartarea.innerHeight();
if ($chartarea.find('svg').length > 0) {
$chartarea.find('svg').remove();
}
var margin = {top: 20, right: 20, bottom: 20, left: 20};
var width = ca_w - margin.left - margin.right,
height = ca_h - margin.top - margin.bottom;
var g = d3.select('#chartarea').append('svg')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append('g')
.style('position', 'relative')
.style('left', '0')
.attr('height', height)
.attr('width', width)
.attr('transform', 'translate('+margin.left+', '+margin.top+')');
switch (int) {
case 0:
chartOne(g, width, height);
break;
case 1:
chartTwo(g, width, height);
break;
default:
chartOne(g, width, height);
}
}
Donut chart func
function chartOne(g, width, height) {
var data = [
{name: "USA", value: 40},
{name: "UK", value: 20},
{name: "Canada", value: 30},
{name: "Maxico", value: 10},
];
var text = "";
var thickness = 40;
var radius = Math.min(width, height) / 2;
var color = d3.scaleOrdinal(d3.schemeCategory10);
var arc = d3.arc()
.innerRadius(radius - thickness)
.outerRadius(radius);
var pie = d3.pie()
.value(function(d) { return d.value; })
.sort(null);
g.selectAll('path')
.data(pie(data))
.enter()
.append("g")
.on("mouseover", function(d) {
let g = d3.select(this)
.style("cursor", "pointer")
.style("fill", "black")
.append("g")
.attr("class", "text-group");
g.append("text")
.attr("class", "name-text")
.text(d.data.name)
.attr('text-anchor', 'middle')
.attr('dy', '-1.2em');
g.append("text")
.attr("class", "value-text")
.text(d.data.value)
.attr('text-anchor', 'middle')
.attr('dy', '.6em');
})
.on("mouseout", function() {
d3.select(this)
.style("cursor", "none")
.style("fill", color(this._current))
.select(".text-group").remove();
})
.append('path')
.attr('d', arc)
.attr('fill', (d,i) => color(i))
.on("mouseover", function() {
d3.select(this)
.style("cursor", "pointer")
.style("fill", "black");
})
.on("mouseout", function() {
d3.select(this)
.style("cursor", "none")
.style("fill", color(this._current));
})
.each(function(d, i) { this._current = i; });
g.append('text')
.attr('text-anchor', 'middle')
.attr('dy', '.35em')
.text(text);
}
Adding a translate to adjust for the width and height can be added to chartOne() function:
g.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
Now you can add the margins and finish up I guess. See demo below:
$(function() {
// on load
$('li').eq(0).addClass('active');
drawChart(0);
$('li').on('click', function() {
var index = $(this).index();
$('li').removeClass('active');
$(this).addClass('active');
drawChart(index);
});
});
function drawChart(int) {
var $chartarea = $('#chartarea'),
ca_w = $chartarea.innerWidth(),
ca_h = $chartarea.innerHeight();
if ($chartarea.find('svg').length > 0) {
$chartarea.find('svg').remove();
}
var margin = {
top: 20,
right: 20,
bottom: 20,
left: 20
};
var width = ca_w - margin.left - margin.right,
height = ca_h - margin.top - margin.bottom;
var g = d3.select('#chartarea').append('svg')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append('g')
.style('position', 'relative')
.style('left', '0')
.attr('height', height)
.attr('width', width)
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
switch (int) {
case 0:
chartOne(g, width, height, margin);// edited
break;
case 1:
chartTwo(g, width, height);
break;
default:
chartOne(g, width, height, margin);// edited
}
}
function chartTwo(g, width, height) {
g.append('line')
.attr('x1', 0)
.attr('y1', 0)
.attr('x2', width)
.attr('y2', height)
.attr('stroke', 'grey')
.attr('stroke-width', '10px');
g.append('line')
.attr('x1', width)
.attr('y1', 0)
.attr('x2', 0)
.attr('y2', height)
.attr('stroke', 'grey')
.attr('stroke-width', '10px');
}
function chartOne(g, width, height, margin) { // edited
// ADDED THIS
g.attr("transform", "translate(" + (width / 2 + margin.left) + "," + (height / 2 + margin.top) + ")");
var data = [{
name: "USA",
value: 40
},
{
name: "UK",
value: 20
},
{
name: "Canada",
value: 30
},
{
name: "Maxico",
value: 10
},
];
var text = "";
var thickness = 40;
var radius = Math.min(width, height) / 2;
var color = d3.scaleOrdinal(d3.schemeCategory10);
var arc = d3.arc()
.innerRadius(radius - thickness)
.outerRadius(radius);
var pie = d3.pie()
.value(function(d) {
return d.value;
})
.sort(null);
g.selectAll('path')
.data(pie(data))
.enter()
.append("g")
.on("mouseover", function(d) {
let g = d3.select(this)
.style("cursor", "pointer")
.style("fill", "black")
.append("g")
.attr("class", "text-group");
g.append("text")
.attr("class", "name-text")
.text(d.data.name)
.attr('text-anchor', 'middle')
.attr('dy', '-1.2em');
g.append("text")
.attr("class", "value-text")
.text(d.data.value)
.attr('text-anchor', 'middle')
.attr('dy', '.6em');
})
.on("mouseout", function() {
d3.select(this)
.style("cursor", "none")
.style("fill", color(this._current))
.select(".text-group").remove();
})
.append('path')
.attr('d', arc)
.attr('fill', (d, i) => color(i))
.on("mouseover", function() {
d3.select(this)
.style("cursor", "pointer")
.style("fill", "black");
})
.on("mouseout", function() {
d3.select(this)
.style("cursor", "none")
.style("fill", color(this._current));
})
.each(function(d, i) {
this._current = i;
});
g.append('text')
.attr('text-anchor', 'middle')
.attr('dy', '.35em')
.text(text);
}
* {
margin: 0;
padding: 0;
}
#chartarea {
margin: 20px;
border: solid 1px black;
height: 300px;
width: 500px;
}
ul {
display: flex;
width: 500px;
margin: 20px;
list-style: none;
text-align: center;
}
li {
margin: 0 20px;
padding: 5px;
border-radius: 10px;
flex: 1;
background: grey;
cursor: pointer;
}
li.active {
background: #60cafe
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js"></script>
<div id="chartarea" class="charts--item"></div>
<ul>
<li>Chart One</li>
<li>Chart Two</li>
</ul>
Your pie/donut chart is positioned with a center at [0,0] while your x is comprised of lines with endpoints like this one:
.attr('x1', 0)
.attr('y1', 0)
.attr('x2', width)
.attr('y2', height)
Your lines start and end at the corner of the visualization, where as your pie/donut chart is centered on the corner.
The easiest way to fix this is to create a g to hold the pie chart that has a different transform than the g to hold the rest of the charts. This new g will have a translate of [width/2,height/2] and will place the center of the pie chart in the center of the visualization. See this fiddle.
Hi I am new in d3js so I am unable to use mouseover event in given code of pie chart...i have a <div> with id named chart so how can I create some class that mouseover event and show a label?
Here is the code that I am using to draw pie chart:
var w = 300;
var h = 300;
var dataset = [
{"year":"2017-07-01","value":"5"},
{"year":"2017-07-02","value":"10"},
{"year":"2017-07-03","value":"15"},
{"year":"2017-07-04","value":"20"},
{"year":"2017-07-05","value":"25"},
{"year":"2017-07-06","value":"30"},
{"year":"2017-07-07","value":"35"},
{"year":"2017-07-08","value":"40"},
{"year":"2017-07-09","value":"45"},
{"year":"2017-07-10","value":"50"},
{"year":"2017-07-11","value":"55"},
{"year":"2017-07-12","value":"60"},
{"year":"2017-07-13","value":"65"},
{"year":"2017-07-14","value":"70"}
];
var outerRadius = w / 2;
var innerRadius = 0;
var arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var pie = d3.layout.pie()
.value(function(d) {
return d.value;
});
var color = d3.scale.category20();
var svg = d3.select("#chart")
.append("svg")
.attr("width", w)
.attr("height", h);
var arcs = svg.selectAll("g.arc")
.data(pie(dataset))
.enter()
.append("g")
.attr("class", "arc")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");
arcs.append("path")
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
arcs.append("text")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor", "middle")
.text(function(d) {
return d.value;
});
Add Styles on your HTML
<style>
#chart {
height: 360px;
position: relative;
width: 360px;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #333;
display: none;
font-size: 12px;
left: 130px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
width: 80px;
z-index: 10;
}
.legend {
font-size: 12px;
}
rect {
stroke-width: 2;
}
</style>
JS side
var width = 360;
var height = 360;
var radius = Math.min(width, height) / 2;
var donutWidth = 75;
var legendRectSize = 18;
var legendSpacing = 4;
var color = d3.scale.category20b();
var svg = d3.select('#chart')
.append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + (width / 2) +
',' + (height / 2) + ')');
var arc = d3.svg.arc()
.innerRadius(radius - donutWidth)
.outerRadius(radius);
var pie = d3.layout.pie()
.value(function(d) { return d.count; })
.sort(null);
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(dataset))
.enter()
.append('path')
.attr('d', arc)
.attr('fill', function(d, i) {
return color(d.data.label);
});
path.on('mouseover', function(d) {
var total = d3.sum(dataset.map(function(d) {
return d.count;
}));
var percent = Math.round(1000 * d.data.count / total) / 10;
tooltip.select('.label').html(d.data.label);
tooltip.select('.count').html(d.data.count);
tooltip.select('.percent').html(percent + '%');
tooltip.style('display', 'block');
});
path.on('mouseout', function() {
tooltip.style('display', 'none');
});
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 = -2 * legendRectSize;
var vert = i * height - offset;
return 'translate(' + horz + ',' + vert + ')';
});
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; });
I hope this helps you. You might have to work around, it depends on how you want to show tool tip and how you populate data in your chart.
I assume that what you want is a tooltip. The easiest way to do this is to append an svg:title element to each circle, as the browser will take care of showing the tooltip and you don't need the mousehandler. The code would be something like
vis.selectAll("circle")
.data(datafiltered).enter().append("svg:circle")
...
.append("svg:title")
.text(function(d) { return d.x; });
If you want fancier tooltips, you could use tipsy for example. See here for an example.
I have a requirement to update a d3 pie chart. I am able to update the arcs properly, but I am having issues in updating the label on the center. I am showing the sum of numbers in the label in the center. Can someone help me with this ?
Please find the plunk below.
https://plnkr.co/edit/L9uBnyZmt2TDvLJDUSE1?p=info
path = path.data(pie(dataset));
svg.selectAll('text').data(pie(dataset)).enter()
.text(function (d) {
return (25);
})
.transition()
.duration(1000)
.style("opacity", 1);
textG.select("text")
.style("opacity", 0)
.attr("transform", function (d) {
return "translate(" + arc.centroid(d) + ")";
})
.data(pie(dataset))
.text(function (d) {
return d.data['count'];
})
.transition()
.duration(1000)
.style("opacity", 1);
path.transition()
.duration(750)
.attrTween('d', function (d) {
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function (t) {
return arc(interpolate(t));
};
});
Am changing the data set on click on the legend. You can see that the arc refreshes, but not the label in the center
Am new to D3 and still figuring things out.
Thanks in advance.
You should also update the center text and other labels in click listener.
var sum = d3.sum(dataset, function(d) {
return d.count;
});
svg.select("text.centerText")
.text(sum);
textG.data(pie(dataset));
textG.select("text")
.transition()
.duration(750)
.attr('transform', function(d) {
return 'translate(' + arc.centroid(d) + ')';
})
.text(function(d, i) {
return d.data.count > 0 ? d.data.count : '';
});
(function(d3) {
'use strict';
var width = 360;
var height = 300;
var radius = Math.min(width, height) / 4;
var donutWidth = 40;
var legendRectSize = 18;
var legendSpacing = 4;
var data1 = [{
'label': 'Label 1',
count: 5
},
{
'label': 'Label 2',
count: 10
},
{
'label': 'Label 3',
count: 15
}
];
var data2 = [{
'label': 'Label 1',
count: 30
},
{
'label': 'Label 2',
count: 20
},
{
'label': 'Label 3',
count: 9
}
];
var color = d3.scaleOrdinal(d3.schemeCategory20b);
var svg = d3.select('#chart')
.append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + (width / 2) +
',' + (height / 2) + ')');
var arc = d3.arc()
.innerRadius(radius - donutWidth)
.outerRadius(radius);
var pie = d3.pie()
.value(function(d) {
return d.count;
})
.sort(null);
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 dataset = data1;
var isDataSet1 = true;
var path = svg.selectAll('path')
.data(pie(dataset))
.enter()
.append('path')
.attr('d', arc)
.attr('fill', function(d, i) {
return color(d.data.label);
}) // UPDATED (removed semicolon)
.each(function(d) {
this._current = d;
});
var sum = d3.sum(dataset, function(d) {
return d.count;
});
var centerText = svg.append("text")
.attr('class', 'centerText')
.attr('dy', '0.35em')
.attr('text-anchor', 'middle')
.attr('color', 'black')
.text(sum);
var textG = svg.selectAll('.labels')
.data(pie(dataset))
.enter().append('g')
.attr('class', 'labels');
textG.append('text')
.attr('transform', function(d) {
return 'translate(' + arc.centroid(d) + ')';
})
.attr('dy', '.35em')
.style('text-anchor', 'middle')
.attr('fill', '#fff')
.text(function(d, i) {
return d.data.count > 0 ? d.data.count : '';
});
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 = 5 * legendRectSize;
var vert = i * height - offset;
return 'translate(' + horz + ',' + vert + ')';
});
legend.append('rect')
.attr('width', 10)
.attr('height', 10)
.style('fill', color)
.style('stroke', color)
.attr('rx', 5)
.attr('ry', 5) // UPDATED (removed semicolon)
.on('click', function(label) {
if (isDataSet1) {
dataset = data2;
} else {
dataset = data1;
}
isDataSet1 = !isDataSet1;
var rect = d3.select(this);
pie.value(function(d) {
return d.count;
});
path = path.data(pie(dataset));
path.transition()
.duration(750)
.attrTween('d', function(d) {
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
return arc(interpolate(t));
};
});
var sum = d3.sum(dataset, function(d) {
return d.count;
});
svg.select("text.centerText")
.text(sum);
textG.data(pie(dataset));
textG.select("text")
.transition()
.duration(750)
.attr('transform', function(d) {
return 'translate(' + arc.centroid(d) + ')';
})
.text(function(d, i) {
return d.data.count > 0 ? d.data.count : '';
});
});
legend.append('text')
.attr('x', 13 + legendSpacing)
.attr('y', 13 - legendSpacing)
.text(function(d) {
return d;
});
})(window.d3);
#chart {
margin: 0 auto;
position: relative;
/*height: 360px;
width: 360px;*/
}
.tooltip {
background: #eee;
box - shadow: 0 0 5 px #999999;
color: # 333;
display: none;
font - size: 12 px;
left: 130 px;
padding: 10 px;
position: absolute;
text - align: center;
top: 95 px;
width: 80 px;
z - index: 10;
}
.legend {
font - size: 12 px;
}
rect {
cursor: pointer;
stroke - width: 2;
}
rect.disabled {
fill: transparent!important;
}
h1 {
font - size: 14 px;
text - align: center;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<body>
<h1>Toronto Parking Tickets by Weekday in 2012</h1>
<button type="button" onclick="changeData()">change data</button>
<!-- NEW -->
<div id="chart"></div>
</body>
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. :}
<!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"}
];