Object in D3 Donut - javascript

I know how I can use an array with d3.jsdonuts but I can't seem to understand how objects work with d3.js.
I'd like to output the following object:
Code
var width = 175,
height = 175,
radius = Math.min(width, height) / 2,
donutWidth = 23;
var color = d3.scaleOrdinal(d3.schemeCategory20);
var data = [{
user: 'Bob',
value: 100
},
{
user: 'Danny',
value: 200
}
];
function render(data) {
//data = [100,250];
var svg = d3.select("#pot").append("svg")
.attr("width", width)
.attr("height", height)
var svg_g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var pie = d3.pie()
.sort(null);
var arc = d3.arc()
.innerRadius(radius - donutWidth)
.outerRadius(radius);
var path = svg_g.selectAll("path")
.data(pie(data));
var pathEnter = path.enter().append("path")
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc)
var pathUpdate = path.attr("d", arc);
}
render(data);
JSFiddle
I'd like the values from the object to be rendered.

If you need to show the values in the donut you should add:
.value(function(d) { return d.value }) at var pie = d3.pie().
Something like this:
(function() {
var width = 175,
height = 175,
radius = Math.min(width, height) / 2,
donutWidth = 23;
var color = d3.scaleOrdinal(d3.schemeCategory20);
var data = [{
user: 'Bob',
value: 100
}, {
user: 'Danny',
value: 200
}, {
user: 'Test',
value: 50
}];
function render(data) {
var svg = d3.select("#pot").append("svg")
.attr("width", width)
.attr("height", height)
var svg_g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var pie = d3.pie().value(function(d) {
return d.value
})
.sort(null);
var arc = d3.arc()
.innerRadius(radius - donutWidth)
.outerRadius(radius);
var path = svg_g.selectAll("path")
.data(pie(data));
var pathEnter = path.enter().append("path")
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc)
var pathUpdate = path.attr("d", arc);
}
render(data);
})();
<script src="https://d3js.org/d3.v4.min.js"></script>
<div id="pot"></div>

Related

Label text of pie chart not appearing

The labels on my pie chart are not visible, whatever I try (resetting radius, changing text color). The pie chart itself is visible. I have looked at many examples, such as https://bl.ocks.org/santi698/f3685ca8a1a7f5be1967f39f367437c0, but to no avail. There must be something simple that I'm missing, probably in the centroid function. Any help would be appreciated! Code is as follows. It is part of a jinja template, but I guess that's not relevant. Obviously the arcs.append("text") statement is the one that has a mistake somewhere.
<svg width="960" height="500">
</svg>
<script>
var svg = d3.select("svg");
var margin = 50,
width = +svg.attr("width") - margin,
height = +svg.attr("height") - margin,
radius = height / 2;
var g = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
data = [{fruit: "apple", amount: 3},
{fruit: "pear", amount: 2},
{fruit: "kiwi", amount: 5}];
console.log(data);
var colors = ['green', 'red', 'blue'];
var arc = d3.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var labelArc = d3.arc()
.outerRadius(radius - 40)
.innerRadius(radius - 40);
var pie = d3.pie()
.value(function(d) { return d.amount; });
console.log(pie(data))
var arcs = g.selectAll("arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "arc");
arcs.append("path")
.attr("d", arc)
.style('fill', function(d, i) {
return colors[i];
});
arcs.append("text")
.attr("transform", function(d) {
return "translate(" + labelArc.centroid(d) + ")";
})
.text(function(d) {
return d.fruit;
});
</script>
D3 pie generator returns an array of objects with several created properties, among them:
data - the input datum; the corresponding element in the input data array.
Therefore, it should be:
.text(function(d) {
return d.data.fruit;
});
Here is your code with that change:
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg width="960" height="500">
</svg>
<script>
var svg = d3.select("svg");
var margin = 50,
width = +svg.attr("width") - margin,
height = +svg.attr("height") - margin,
radius = height / 2;
var g = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
data = [{
fruit: "apple",
amount: 3
},
{
fruit: "pear",
amount: 2
},
{
fruit: "kiwi",
amount: 5
}
];
var colors = ['green', 'red', 'blue'];
var arc = d3.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var labelArc = d3.arc()
.outerRadius(radius - 40)
.innerRadius(radius - 40);
var pie = d3.pie()
.value(function(d) {
return d.amount;
});
var arcs = g.selectAll("arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "arc");
arcs.append("path")
.attr("d", arc)
.style('fill', function(d, i) {
return colors[i];
});
arcs.append("text")
.attr("transform", function(d) {
return "translate(" + labelArc.centroid(d) + ")";
})
.text(function(d) {
return d.data.fruit;
});
</script>

d3js scroll visibility - series animation for pie chart

I am working on a d3 applicaton - with a pie chart -- I would like to get animation onload and on a call to action. Like when the chart becomes visible during a scroll.
Where the pie segments grow around the central pivot. So tween or snap to the other segment like a relay race
http://jsfiddle.net/pg886/192/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://d3js.org/d3.v3.min.js"></script>
<div class="piechart" data-role="piechart" data-width=400 data-height=400 data-radius=30 data-innerradius=20
data-data=x>
</div>
<style>
.piechart{
/*border: 1px solid black;*/
/*text-align: center;
font-size: 12px;*/
}
</style>
<script>
$( document ).ready(function() {
console.log("test")
var $this = $('.piechart');
var data = [{
"label": "Apples",
"value": 100
},
{
"label": "Pears",
"value": 120
},
{
"label": "Bananas",
"value": 20
}];
var w = $this.data("width");
var h = $this.data("height");
var ir = $this.data("innerradius");
var r = $this.data("radius");
function colores_google(n) {
var colores_g = ["#f7b363", "#448875", "#c12f39", "#2b2d39", "#f8dd2f"];
//var colores_g = ["#47abd5", "#005a70", "#f5a0a3", "#ff7276", "#a9a19c", "#d0743c", "#ff8c00"];
return colores_g[n % colores_g.length];
}
var radius = Math.min(w, h) / 4;
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var labelArc = d3.svg.arc()
.outerRadius(radius - r)
.innerRadius(radius - ir);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.value; });
var chart = d3.select('.piechart').append("svg")
.attr("class", "chart")
.attr("width", w)
.attr("height", h)
.attr("transform", "translate(0,0)");
var piechart = chart
.append("g")
.attr("class", "piechart")
.attr("width", (radius*2))
.attr("transform", "translate(0,"+h/4+")");
var path_group = piechart.append("g")
.attr("class", "path_group")
.attr("transform", "translate(90," + ((h / 4) - 20) + ")");
var padding = 45;
var legendPaddingTop = 30;
var legend = chart.append("g")
.attr("class", "legend")
.attr("width", w/2)
.attr("height", h)
.attr("transform", "translate(" + (w - 50) + "," + (h / 4) + ")");
var label_group = legend.append("svg:g")
.attr("class", "label_group")
.attr("transform", "translate(" + (-(w / 3) + 20) + "," + 0 + ")");
var legend_group = legend.append("svg:g")
.attr("class", "legend_group")
.attr("transform", "translate(" + (-(w / 3) - 100) + "," + 0 + ")");
var g = path_group.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d, i) {
return colores_google(i);
});
var legendHeight = legendPaddingTop;
var ySpace = 18;
//draw labels
var labels = label_group.selectAll("text.labels")
.data(data);
labels.enter().append("svg:text")
.attr("class", "labels")
.attr("dy", function(d, i) {
legendHeight+=ySpace;
return (ySpace * i) + 4;
})
.attr("text-anchor", function(d) {
return "start";
})
.text(function(d) {
return d.label;
});
labels.exit().remove();
//draw labels
//draw legend
var legend = legend_group.selectAll("circle").data(data);
legend.enter().append("svg:circle")
.attr("cx", 100)
.attr("cy", function(d, i) {
return ySpace * i;
})
.attr("r", 7)
.attr("width", 18)
.attr("height", 18)
.style("fill", function(d, i) {
return colores_google(i);
});
legend.exit().remove();
//draw legend
//reset legend height
//console.log("optimum height for legend", legendHeight);
$this.find('.legend').attr("height", legendHeight);
function type(d) {
d.value = +d.value;
return d;
}
});
</script>
So you can achieve this pretty easily, and there are a couple of blocks that will help you.
Arc Tween Firstly this block gives you an example of how to tween an arc. Basically you can't get that automatically so you have to write your own attrTween function. Fortunately this is pretty simple and Mike Bostock gives a really good example in there.
Here's a code sample - but the link gives a really good verbose description of what's going on.
.attrTween("d", function(d) {
var interpolate = d3.interpolate(d.endAngle, newAngle);
return function(t) {
d.endAngle = interpolate(t);
return arc(d);
};
}
Next you want something like this Donut with transitions. This is actually the end-result for where you're trying to get to. This effect is really easy to achieve, all you need to do is set your angles correctly and the timings.
Angles: So here you want both the endAngle and the startAngle to be the same at the start (which should be the endAngle value of the previous segment or 0 for the first segment).
Timing: You want to allow 1 animation to complete before you start the next, simply by delaying them. You can see how that's done with this snippet:
.transition()
.delay(function(d,i) { return i * 500; })
.duration(500)
.attrTween(...)
const dataset = [
{ age: "<5", population: 2704659 },
{ age: "5-13", population: 4499890 },
{ age: "14-17", population: 2159981 },
{ age: "18-24", population: 3853788 },
{ age: "25-44", population: 14106543 },
{ age: "45-64", population: 8819342 },
{ age: "≥65", population: 612463 },
];
const TIME = 2000 / dataset.length;
const color = d3.scaleOrdinal(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
const pie = d3.pie()
.sort(null)
.value(function(d) { return d.population; });
const path = d3.arc()
.innerRadius(0)
.outerRadius(350);
d3.select("#container")
.selectAll(".arc")
.data(pie(dataset))
.enter()
.append("g")
.attr("class", "arc")
.append("path")
.attr("fill", function(d) { return color(d.data.age); })
.transition()
.duration(TIME)
.ease(d3.easeLinear)
.delay(function(d, i) { return i * TIME; })
.attrTween("d", function(d) {
// Note the 0.1 to prevent errors generating the path
const angleInterpolation = d3.interpolate(d.startAngle + 0.1, d.endAngle);
return function(t) {
d.endAngle = angleInterpolation(t);
return path(d);
}
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="800" height="800">
<g id="container" transform="translate(400, 400)"></g>
</svg>

D3 seemingly updating wrong SVG element

I have a d3 layout that is intended to produce 3 charts:
Custom item layout w/ transitions
Pie chart for sales by category (with transitions at some point)
Bar chart for top 5 performing items w/ transitions.
1 & 2 work OK but when I add the third chart, I see some strange behavior. The intention is to create a bar chart where the width of each bar is tied to the sales metric for the top N items determined like so:
data = data.filter(function(d){ return d.date === someDate});
var cf = crossfilter(data);
var salesDimension = cf.dimension(function(d){ return d.sales; });
topData = salesDimension.top(5);
The problem is that instead of drawing the bar chart, my code somehow overwrites the position of 5 items in chart 1 and moves them back to the origin. If I change 5 to 10 above then 10 items are overwritten and so on.
I double checked the scope of my variables and even tried changing the names of everything in my drawTopItems() which made no difference. I suspect that I am doing something incorrectly when it comes to selecting the svg element or applying classes to the svg group elements that I want to modify but I can't for the life of me see what. Can anyone tell me what I might be doing wrong?
Here is my issue in a fiddle: https://jsfiddle.net/Sledge/4eggpd5e/12/.
Here is my javascript code:
var item_width = 40, item_height = 60;
var margin = {top: 50, right: 50, bottom: 75, left: 40},
width = 700 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scaleLinear().range([0, width]);
var y = d3.scaleLinear().range([0, height]);
var colorScale = d3.scaleLinear().domain([500,3000]).range(["white","#4169e1"]);
// Pie Chart parameters
var pieWidth = 300, pieHeight = 300;
var outerRadius = Math.min(pieWidth, pieHeight) / 2,
innerRadius = outerRadius * .50;
var pieColor = d3.scaleOrdinal(['#42b9f4','#3791f2','#374ff1','#25b22e','#107222']); // custom color scale
var legendRectSize = 18; // NEW
var legendSpacing = 4; // NEW
// Top Item Parameters
var topItemMargin = {top:25, right:25, bottom: 25, left: 25};
var topItemWidth = 300 - topItemMargin.left - topItemMargin.right,
topItemHeight = 300 - topItemMargin.top - topItemMargin.bottom;
var topItemXScale = d3.scaleLinear().range([0, topItemWidth]);
var barHeight = 20, barSpacing = 5;
/* SVG */
var svgItemLayout = d3.select("#item_layout")
.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 + ")");
var svgPieChart = d3.select("#pie_chart")
.append("svg")
.attr("width", pieWidth)
.attr("height", pieHeight)
.append("g")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")") ;
var svgTopItems = d3.select("#top_items")
.append("svg")
.attr("width", topItemWidth)
.attr("height", topItemHeight)
.append("g")
.attr("transform", "translate(" + topItemMargin.left + "," + topItemMargin.top + ")");
/* DRAW FUNCTIONS */
// a single function to draw
function drawItemLayout(data, someDate){
data.forEach(function(d) {
d.x_pos = +d.x_pos;
d.y_pos = +d.y_pos;
d.sales = +d.sales;
});
// pre-filter data
data = data.filter(function(d){ return d.date === someDate});
var x_offset = 5, y_offset = 5;
x.domain(d3.extent(data, function(d) { return d.x_pos; })); // set the x domain
y.domain(d3.extent(data, function(d) { return d.y_pos; })); // set the y domain
// create an update selection with a key function
var g_sel = svgItemLayout.selectAll("g")
.data(data, function(d){
return d.item_name;
});
// get rid of those leaving the update
g_sel.exit().remove();
// our entering g
var g_ent = g_sel.enter()
.append("g");
// add our rects to our g
g_ent.append("rect")
.attr("class", "dot") // wonder if I really need this class?
.attr("width", item_width)
.attr("height", item_height)
.attr("rx", 3)
.attr("ry", 3)
.style("fill", function(d){ return colorScale(d.sales); }) // color factor variable
.style("fill-opacity", 0.5);
// add our text to our g
g_ent.append("text")
.attr("font-size", 10)
.attr("text-anchor", "middle")
.attr("fill", "black")
.attr("dx", item_width/2)
.attr("dy", item_height/2)
.text(function(d){ return d.item_name; });
// UPDATE + ENTER selection
g_sel = g_ent.merge(g_sel);
// move them into position with transition
g_sel
.transition()
.duration(1200)
.delay(function(d, i) { return i *40; })
.attr("transform", function(d){
return "translate(" + (x(d.x_pos) + x_offset) + "," + (y(d.y_pos) + y_offset) + ")";
});
}
function drawPieChart(data, someDate) {
data.forEach(function(d) {
d.x_pos = +d.x_pos;
d.y_pos = +d.y_pos;
d.sales = +d.sales;
});
// pre-filter data
data = data.filter(function(d){ return d.date === someDate});
var cf = crossfilter(data);
var salesDimension = cf.dimension(function(d){ return d.sales; });
var categoryDimension = cf.dimension(function(d){ return d.category; });
var categoryGroup = categoryDimension.group();
function reduceInitial(p, v) {
return {
sales : 0,
count : 0
};
}
function reduceAdd(p, v) {
p.sales = p.sales + v.sales;
p.count = p.count + 1;
return p;
}
function reduceRemove(p, v) {
p.sales = p.sales - v.sales;
p.count = p.count - 1;
return p;
}
categoryAggregated = categoryGroup.reduce(reduceAdd, reduceRemove, reduceInitial).all();
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var pie = d3.pie()
.value(function(d) { return d.value.sales; })
.sort(null);
var path = svgPieChart.selectAll('path')
.data(pie(categoryAggregated))
.enter()
.append('path')
.attr('d', arc)
.attr('fill', function(d, i) { return pieColor(i);});
// Add a legend:
var legend = svgPieChart.selectAll('.legend')
.data(pieColor.domain())
.enter()
.append('g')
.attr('class', 'legend')
.attr('transform', function(d, i) {
var height = legendRectSize + legendSpacing;
var offset = height * pieColor.domain().length / 2;
var horz = -3 * legendRectSize;
var vert = i * height - offset;
return 'translate(' + horz + ',' + vert + ')';
});
legend.append('rect')
.attr('width', legendRectSize)
.attr('height', legendRectSize)
.style('fill', pieColor)
.style('stroke', pieColor);
legend.append('text')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.text(function(d) { return categoryAggregated[d].key; }); // returns text based on data index
}
function drawTopItems (data, someDate) {
data.forEach(function(d) {
d.x_pos = +d.x_pos;
d.y_pos = +d.y_pos;
d.sales = +d.sales;
});
// pre-filter data
data = data.filter(function(d){ return d.date === someDate});
var cf = crossfilter(data);
var salesDimension = cf.dimension(function(d){ return d.sales; });
topData = salesDimension.top(5);
topItemXScale.domain(d3.extent(topData, function(d) { return d.sales; })); // set the x domain
var f_sel = svgTopItems.selectAll("g")
.data(topData,function(d){ return d.item_name; }).enter();
f_sel.exit().remove();
var f_ent = f_sel.enter().append("g");
f_ent.append("rect")
.attr("class", "dot") // wonder if I really need this class?
.attr("width", function(d){ return d.sales })
.attr("height", barHeight)
.style("fill","#351eff") // color factor variable
.style("fill-opacity", 0.75);
// add our text to our g
f_ent.append("text")
.attr("font-size", 10)
.attr("text-anchor", "left")
.attr("fill", "black")
.attr("dx", item_width/2)
.attr("dy", item_height/2)
.text(function(d){ return d.item_name});
// UPDATE + ENTER selection
f_sel = f_ent.merge(f_sel);
f_sel.transition()
.duration(1200)
.delay(function(d, i) { return i *40; })
.attr("transform", function(d, i){
return "translate( 0, "+ i*25 +")" + ")";
});
}
/* MAIN */
var data = d3.csvParse( d3.select("pre#data").text());
drawItemLayout(data, '1-20-2017');
drawPieChart(data, '1-20-2017');
drawTopItems(data, '1-20-2017');
/* UPDATE DATA */
function updateData(date) {
//d3.csv("http://localhost:8080/udacity_test_vis_1/output_fixture_data.csv", function(data) {
var data = d3.csvParse( d3.select("pre#data").text());
drawItemLayout (data, date);
drawPieChart(data, date);
drawTopItems(data, date);
}
/* GET SELECTION */
$("#select_params").change(function(){
var date = $("#select_params :selected").val();
console.log(date);
updateData(date);
})
Just three problems:
You are repeating the enter() function:
var f_sel = svgTopItems.selectAll("g")
.data(topData,function(d){ return d.item_name; }).enter();
//this is an enter selection...
var f_ent = f_sel.enter().append("g");
//and you have enter() again here
So, remove the first enter: f_sel should be just the data-binding selection.
Move your merged selection to before appending the rectangles
Your translate has an extra parenthesis:
return "translate( 0, "+ i*25 +")" + ")";
With that problems corrected, this is your updated fiddle: https://jsfiddle.net/utf5hva2/

How to change color of donut chart created using d3.js?

I am very new to d3 charts. I have this code that creates donut charts. However, unable to change colors. could some one help ?
<body>
<div id="chart"></div>
<script src="d3.v3.min.js"></script>
<script>
(function(d3) {
'use strict';
var dataset = [
{ label: 'Abulia', count: 10 },
{ label: 'Betelgeuse', count: 20 },
{ label: 'Cantaloupe', count: 30 },
{ label: 'Dijkstra', count: 40 }
];
var width = 360;
var height = 360;
var radius = Math.min(width, height) / 3.5;
var donutWidth = 50; // NEW
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) // NEW
.outerRadius(radius);
var pie = d3.layout.pie()
.value(function(d) { return d.count; })
.sort(null);
var path = svg.selectAll('path')
.data(pie(dataset))
.enter()
.append('path')
.attr('d', arc)
.attr('fill', function(d, i) {
return color(d.data.label);
});
})(window.d3);
</script>
</body>
</html>
I would like to get donut with these colors #65C400 , #2290EE , #FFC096 .
Is there any other way to create a donut chart with custom values and colors ?? someone pls help.
thanks in advance.
Use ordinal color scales.
var color = d3.scale.ordinal()
.domain(["Abulia", "Betelgeuse", "Cantaloupe","Dijkstra"])
.range(["#65C400" , "#2290EE" , "#FFC096", "#5e5e5e"]);
var dataset = [{
label: 'Abulia',
count: 10
}, {
label: 'Betelgeuse',
count: 20
}, {
label: 'Cantaloupe',
count: 30
}, {
label: 'Dijkstra',
count: 40
}];
var color = d3.scale.ordinal()
.domain(["Abulia", "Betelgeuse", "Cantaloupe","Dijkstra"])
.range(["#65C400" , "#2290EE" , "#FFC096", "#5e5e5e"]);
var width = 360;
var height = 360;
var radius = Math.min(width, height) / 3.5;
var donutWidth = 50; // NEW
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) // NEW
.outerRadius(radius);
var pie = d3.layout.pie()
.value(function(d) {
return d.count;
})
.sort(null);
var path = svg.selectAll('path')
.data(pie(dataset))
.enter()
.append('path')
.attr('d', arc)
.attr('fill', function(d, i) {
return color(d.data.label);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="chart"></div>

d3.js dynamic data with labels

I've managed to get the following working (pie chart changing dynamically based on a slider value):
var x = function() {
return $("#slider").val();
}
var data = function() {
return [x(), ((100-x())/2), ((100-x())/2)];
}
var w = 100,
h = 100,
r = 50,
color = d3.scale.category20(),
pie = d3.layout.pie().sort(null),
arc = d3.svg.arc().outerRadius(r);
var svg = d3.select("#chart").append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");
var arcs = svg.selectAll("path")
.data(pie(data()))
.enter().append("svg:path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc)
.each(function(d) { this._current = d; });
var redraw = function() {
newdata = data(); // swap the data
arcs = arcs.data(pie(newdata)); // recompute the angles and rebind the data
arcs.transition().duration(750).attrTween("d", arcTween); // redraw the arcs
};
// Store the currently-displayed angles in this._current.
// Then, interpolate from this._current to the new angles.
function arcTween(a) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function(t) {
return arc(i(t));
};
}
I can't seem to modify it to include dynamic labels (use an object for data rather than an array {'label': 'label1', 'value': value}. How would I modify the above code to add labels?
This should work, keeping the labels and the pie chart as separate entities:
var x = function() {
return $("#slider").val();
}
var data = function() {
return [x(), ((100-x())/2), ((100-x())/2)];
}
var labels = function() {
var label1 = "LABEL 1: " + x();
var label2 = "LABEL 2: " + ((100-x())/2);
var label3 = "LABEL 3: " + ((100-x())/2);
return [label1, label2, label3];
}
var w = 200,
h = 100,
r = 50,
color = d3.scale.category20(),
pie = d3.layout.pie().sort(null),
arc = d3.svg.arc().outerRadius(r);
var svg = d3.select("#chart").append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + 50 + "," + h / 2 + ")");
var arcs = svg.selectAll("path")
.data(pie(data()))
.enter().append("svg:path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc)
.each(function(d) { this._current = d; });
var label_group = svg.selectAll("text")
.data(labels())
.enter()
.append("text")
.text(function(d) {
return d;
})
.attr("x", 60)
.attr("y", function(d, i) { return (i * 20) - 16; });
var redraw = function() {
newdata = data(); // swap the data
arcs = arcs.data(pie(newdata)); // recompute the angles and rebind the data
arcs.transition().duration(750).attrTween("d", arcTween); // redraw the arcs
label_group = label_group.data(labels());
label_group.transition().delay(300).text(function(d) {
return d;
});

Categories

Resources