d3js get data from multidimensional array - arrays

I'm working on a d3js donut chart and I'm trying to feed data in from a multidimensional array: fiddle
Output of topHoldersArray:
{
"1":{"address":"0xd35a2d8c651f3eba4f0a044db961b5b0ccf68a2d","amount":"309953166.54621424","percent":"30.9953%"},
"2":{"address":"0xe17c20292b2f1b0ff887dc32a73c259fae25f03b","amount":"200000001","percent":"20.0000%"},
"3":{"address":"0x0000000000000000000000000000000000000000","amount":"129336426","percent":"12.9336%"}
}
With this array I get the error:
Uncaught TypeError: Cannot read property 'startAngle' of undefined
How can I feed this array into the graph? It seems the issue is that it's a multidimensional array but I"m not sure how to access it for the data points
Here's a snippet illustrating the problem:
var topHoldersArray = [
{
"1":{"address":"0xd35a2d8c651f3eba4f0a044db961b5b0ccf68a2d","amount":"309953166","percent":"30.9953%"},
"2":{"address":"0xe17c20292b2f1b0ff887dc32a73c259fae25f03b","amount":"200000001","percent":"20.0000%"},
"3":{"address":"0x0000000000000000000000000000000000000000","amount":"129336426","percent":"12.9336%"}
}
];
var data = topHoldersArray;
var text = "";
var width = 260;
var height = 260;
var thickness = 40;
var duration = 750;
var radius = Math.min(width, height) / 2;
var color = d3.scaleOrdinal(d3.schemeCategory20);
var svg = d3.select("#topHoldersChart")
.append('svg')
.attr('class', 'pie')
.attr('width', width)
.attr('height', height);
var g = svg.append('g')
.attr('transform', 'translate(' + (width/2) + ',' + (height/2) + ')');
var arc = d3.arc()
.innerRadius(radius - thickness)
.outerRadius(radius);
var pie = d3.pie()
.value(function(d) { return d.amount; })
.sort(null);
var path = 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.address}`)
.attr('text-anchor', 'middle')
.attr('dy', '-1.2em');
g.append("text")
.attr("class", "value-text")
.text(`${d.data.amount}`)
.attr('text-anchor', 'middle')
.attr('dy', '.6em');
})
.on("mouseout", function(d) {
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(d) {
d3.select(this)
.style("cursor", "pointer")
.style("fill", "black");
})
.on("mouseout", function(d) {
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);
.pie {
margin: 20px;
}
.pie text {
font-family: "Verdana";
fill: #888;
}
.pie .name-text{
font-size: 1em;
}
.pie .value-text{
font-size: 3em;
}
<div class="token-chart">
<h6>Top Holders</h6>
<div class="chart" id="topHoldersChart"></div>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>

Let's look at your d3.pie layout:
var pie = d3.pie()
.value(function(d) { return d.amount; })
.sort(null);
When we feed data to this (pie(data)), pie is expecting an array. But you are providing an object:
{
"1":{"address":"0xd35a2d8c651f3eba4f0a044db961b5b0ccf68a2d","amount":"309953166.54621424","percent":"30.9953%"},
"2":{"address":"0xe17c20292b2f1b0ff887dc32a73c259fae25f03b","amount":"200000001","percent":"20.0000%"},
"3":{"address":"0x0000000000000000000000000000000000000000","amount":"129336426","percent":"12.9336%"}
}
We need to convert this to an array to feed it to d3.pie(). For this we could use d3.entries() (though there are other ways to achieve this too).
d3.entries() takes an object, say:
{ a: value1, b: value2 }
And converts it to an array:
[ { key: "a", value: value1 }, {key: "b", value: value2 } ]
The values are now within a property called value. This requires us to look up the amount at d.value.amount. For example:
var topHoldersArray =
{
"1":{"address":"0xd35a2d8c651f3eba4f0a044db961b5b0ccf68a2d","amount":"309953166","percent":"30.9953%"},
"2":{"address":"0xe17c20292b2f1b0ff887dc32a73c259fae25f03b","amount":"200000001","percent":"20.0000%"},
"3":{"address":"0x0000000000000000000000000000000000000000","amount":"129336426","percent":"12.9336%"}
};
var data = d3.entries(topHoldersArray);
var text = "";
var width = 260;
var height = 260;
var thickness = 40;
var duration = 750;
var radius = Math.min(width, height) / 2;
var color = d3.scaleOrdinal(d3.schemeCategory20);
var svg = d3.select("#topHoldersChart")
.append('svg')
.attr('class', 'pie')
.attr('width', width)
.attr('height', height);
var g = svg.append('g')
.attr('transform', 'translate(' + (width/2) + ',' + (height/2) + ')');
var arc = d3.arc()
.innerRadius(radius - thickness)
.outerRadius(radius);
var pie = d3.pie()
.value(function(d) { return d.value.amount; })
.sort(null);
var path = 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.value.address}`)
.attr('text-anchor', 'middle')
.attr('dy', '-1.2em')
g.append("text")
.attr("class", "value-text")
.text(`${d.data.value.amount}`)
.attr('text-anchor', 'middle')
.attr('dy', '.6em')
})
.on("mouseout", function(d) {
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(d) {
d3.select(this)
.style("cursor", "pointer")
.style("fill", "black");
})
.on("mouseout", function(d) {
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);
.pie {
margin: 20px;
}
.pie text {
font-family: "Verdana";
fill: #888;
}
.pie .name-text{
font-size: 1em;
}
.pie .value-text{
font-size: 3em;
}
<div class="token-chart">
<h6>Top Holders</h6>
<div class="chart" id="topHoldersChart"></div>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>

Related

Make Axis line grey or reduce opacity

I want to make the axis lines either less opaque, or make them light grey. I tried to just do .style(opacity, 0.5), but it only makes the TICKS opaque, not the actual line itself. I want to make the ACTUAL LINE less opaque/light grey. I also tried adding the call(d3.axisLeft...).style(less opaque) approach but I still get nothing. How do I go about doing that?
import React, {Component, useRef, useEffect} from 'react';
import ExperienceScoresData from './experience_scores';
import * as d3 from "d3";
import { select, csv} from 'd3';
import { extent, max, min } from "d3-array";
ExperienceScoresData.map(function(val){
val.customerExperienceScore *= 100;
return 0;
})
class Linechart extends Component {
constructor(props){
super(props)
this.createBarChart = this.createBarChart.bind(this)
}
componentDidMount() {
this.createBarChart()
}
componentDidUpdate() {
this.createBarChart()
}
createBarChart() {
var margin = {top: 85, right: 60, bottom: 60, left: 80},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var node = this.node
var divObj = select(node)
var svgObj = divObj
.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 + ")");
//Read the data
d3.csv("https://raw.githubusercontent.com/QamarFarooq/data-for-testing/main/5_OneCatSevNumOrdered.csv", function(data) {
// group the data: I want to draw one line per group
var sumstat = d3.nest() // nest function allows to group the calculation per level of a factor
.key(function(d) { return d.name;})
.entries(data);
//console.log(sumstat)
// Define the div for the tooltip
var tooltip = divObj
.append("div")
.attr("class","tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "1px")
.style("border-radius", "5px")
.style("padding", "10px")
.text("I AM A TOOLTIP pakistan zindabad");
// Add title for linechart
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 25)
.attr("x", 110)
.attr("y", -50)
.text("Online Ratings");
// Add X axis --> it is a date format
var x = d3.scaleLinear()
.domain(d3.extent(data, function(d) { return d.year; }))
.range([ 0, width ]);
svgObj.append("g")
.attr("transform", "translate(0," + height + ")")
.attr("stroke-width","0.3")
.style("opacity","0.5")
.call(d3.axisBottom(x).tickSize(-height).tickFormat('').ticks(5));
// ticks
svgObj.append("g")
.style("opacity","0.85")
.style("font", "14px times")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(5));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) { return +d.n; })])
.range([ height, 0 ]);
svgObj.append("g")
.attr("stroke-width","0.3")
.style("opacity","0.5")
.call(d3.axisLeft(y).tickSize(-width).tickFormat('').ticks(5));
// ticks
svgObj.append("g")
.style("opacity","0.85")
.style("font", "14px times")
.call(d3.axisLeft(y).ticks(5));
// Add X axis label:
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 20)
.attr("x", width/2 + margin.left)
.attr("y", height + 50)
.style("fill", d3.color("grey"))
.text("Year Of Birth");
// Add Y axis label:
svgObj.append("text")
.attr("text-anchor", "end")
.attr("font-size", 20)
.attr("transform", "rotate(-90)")
.attr("x", -height/2 + 40)
.attr("y", -margin.left + 25)
.style("fill", d3.color("grey"))
.text("N-Value")
// color palette
var key = sumstat.map(function(d){ return d.key }) // list of group names
var color = d3.scaleOrdinal()
.domain(key)
.range(['#e41a1c','#377eb8','#4daf4a'])
// Add one DOT in the legend for each name.
svgObj.selectAll(".dots")
.data(key)
.enter()
.append("circle")
.attr("cx", function(d,i){ return 250 + i*120})
.attr("cy", -30)
.attr("r", 7)
.style("fill", function(d){ return color(d)})
// Add LABEL for legends of each dot.
svgObj.selectAll(".labels")
.data(key)
.enter()
.append("text")
.style("fill", d3.color("grey"))
.attr("x", function(d,i){ return 270 + i*120})
.attr("y", -28)
.text(function(d){ return d})
.attr("text-anchor", "left")
.style("alignment-baseline", "middle")
// Draw the line
svgObj.selectAll(".line")
.data(sumstat)
.enter()
.append("path")
.attr("fill", "none")
.attr("stroke", function(d){ return color(d.key) })
.attr("stroke-width", 4.5)
.attr("d", function(d){
return d3.line()
.curve(d3.curveMonotoneX)
.x(function(d) { return x(d.year); })
.y(function(d) { return y(+d.n); })
(d.values)
})
.on("mouseover", function(){return tooltip.style("visibility", "visible");})
.on("mousemove", function(){return tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px");})
.on("mouseout", function(){return tooltip.style("visibility", "hidden");})
var dataUnpacked = sumstat.map( function(d){return d.values})
console.log(data)
// Draw dots on points
svgObj.selectAll(".lineChartDots")
.data(data)
.enter()
.append("circle")
.attr("class","lineChartDots")
.style("fill","white")
.style("stroke-width", "3px")
.style("stroke", function (d) { return color(d.name) })
.attr("cx", function(d) {return x(d.year); })
.attr("cy", function(d) {return y(d.n); })
.attr("r", 5.5)
})
}
render() {
return <div ref={node => this.node = node} className="example_div"> </div>
}
}
export default Linechart;
The following could change the axis line's opacity.
svg.append("g")
.style("opacity", 0.5)
.call(d3.axisLeft(y))
.call(g => { // manipulate the elements' attrs here
g.select("path")
.attr("opacity", 0.5)
});
I run your code and found that the above code actually worked but since there are two svg lines in the axis, both the axis path and the first background grid line, so you might feel the opacity wasn't changed. See jsfiddle here.
a simple demo:
<!DOCTYPE html>
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<script>
// set the dimensions and margins of the graph
var margin = {top: 10, right: 30, bottom: 30, left: 60},
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.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 + ")");
//Read the data
d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/3_TwoNumOrdered_comma.csv",
// When reading the csv, I must format variables:
function(d){
return { date : d3.timeParse("%Y-%m-%d")(d.date), value : d.value }
},
// Now I can use this dataset:
function(data) {
// Add X axis --> it is a date format
var x = d3.scaleTime()
.domain(d3.extent(data, function(d) { return d.date; }))
.range([ 0, width ]);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) { return +d.value; })])
.range([ height, 0 ]);
svg.append("g")
.style("opacity", 0.5)
.call(d3.axisLeft(y))
.call(g => {
g.select("path")
.attr("opacity", 0.5)
});
// Add the line
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(function(d) { return x(d.date) })
.y(function(d) { return y(d.value) })
)
})
</script>

x-axis horizontal line and y-axis labels are not displaying in D3 Grouped bar chart

I am creating grouped bar chart using D3 V5 in react.I am able to display y axis but not ticks and text.but in case of x-axis it's completely invisible. i have added d3.min.js to index.html file, but nothing works. any help is appreciated
here I am attaching my code
DrawChart = (data) => {
var w = 450, h = 300, p = 100;
var x0 = d3.scaleBand().range([0, w]).padding(0.4);
var x1 = d3.scaleBand();
var y = d3.scaleLinear().range([h, 0]);
var color = d3.scaleOrdinal().range(["#a85db3", "#95f578"]);
const svg = d3.select("div#predicative")
.append("svg").attr("width", w).attr("height", h)
.attr("padding", p).style("margin-left", 30)
.style("margin-top", 20).style("margin-bottom", 10);
var ageNames = d3.keys(data[0]).filter(function (key) { return key !== "dept"; });
data.forEach(function (d) {
d.ages = ageNames.map(function (name) { return { name: name, value: +d[name] }; });
});
x0.domain(data.map(function (d) { return d.dept; }));
x1.domain(ageNames).rangeRound([0, x0.bandwidth()]);
y.domain([0, (d3.max(data, function (d) { return d3.max(d.ages, function (d) { return d.value; }); })) + 10]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(d3.axisBottom(x0)
.tickSize(-w, 0, 0)
.tickFormat(''));
svg.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(y))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Time");
svg:not(:root){
overflow: visible;
}

Elasticsearch- Nested Aggregations D3

I am trying to create D3 charts based on elasticsearch nested aggregation. While I can plot a chart based on the first aggregation, I am not sure why I cant plot a similar chart on the nested a subsequent aggregation. Can anyone suggest what I should do?
My code:
esClient.search({
index: 'vehicle',
body: {
query:{
match:{
_all:searchTerms
}
},
aggs: {
touchdowns: {
terms: {
field: "country",
size:5
},
aggs: {
corp: {
terms: {
field: "companyName",
size:5
}
}
},
}
},
sort: [sortObject],
from: resultsPage * 10,
}
}).then(function(es_return){
deferred.resolve(es_return);
//// Pie Chart first aggregation
var touchdowns = es_return.aggregations.touchdowns.buckets;
// d3 donut chart
var width = 600,
height = 300,
radius = Math.min(width, height) / 2;
var color = ['#ff7f0e', '#d62728', '#2ca02c', '#1f77b4'];
var arc = d3.svg.arc()
.outerRadius(radius - 60)
.innerRadius(120);
var pie = d3.layout.pie()
.sort(null)
.value(function (d) { return d.doc_count; });
var svg = d3.select("#donut-chart").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width/1.4 + "," + height/2 + ")");
var g = svg.selectAll(".arc")
.data(pie(touchdowns))
.enter()
.append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function (d, i) { return color[i]; });
g.append("text")
.attr("transform", function (d) { return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.style("text-anchor", "middle")
.style("fill", "white")
.text(function (d) { return d.data.key; });
//// Pie Chart
var touchdowns = es_return.aggregations.touchdowns.buckets.corp.buckets;
// d3 donut chart
var width = 600,
height = 300,
radius = Math.min(width, height) / 2;
var color = ['#ff7f0e', '#d62728', '#2ca02c', '#1f77b4'];
var arc = d3.svg.arc()
.outerRadius(radius - 60)
.innerRadius(120);
var pie = d3.layout.pie()
.sort(null)
.value(function (d) { return d.doc_count; });
var svg = d3.select("#donut-chart").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width/1.4 + "," + height/2 + ")");
var g = svg.selectAll(".arc")
.data(pie(touchdowns))
.enter()
.append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function (d, i) { return color[i]; });
g.append("text")
.attr("transform", function (d) { return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.style("text-anchor", "middle")
.style("fill", "white")
.text(function (d) { return d.assignee.key; });
}, function(error){
deferred.reject(error);
});
return deferred.promise;};

How to draw Zoomable Sunburst with angular directive?

I am new to d3.js, can anyone guide me about drawing zoomable sunburst.
Thanks in advance !
You might want to check out the D3 gallery of examples, specifically the zoomable sunburst:
http://bl.ocks.org/mbostock/4348373
Code from their example:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
path {
stroke: #fff;
fill-rule: evenodd;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var width = 960,
height = 700,
radius = Math.min(width, height) / 2;
var x = d3.scale.linear()
.range([0, 2 * Math.PI]);
var y = d3.scale.sqrt()
.range([0, radius]);
var color = d3.scale.category20c();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + (height / 2 + 10) + ")");
var partition = d3.layout.partition()
.value(function(d) { return d.size; });
var arc = d3.svg.arc()
.startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x))); })
.endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx))); })
.innerRadius(function(d) { return Math.max(0, y(d.y)); })
.outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)); });
d3.json("/mbostock/raw/4063550/flare.json", function(error, root) {
if (error) throw error;
var path = svg.selectAll("path")
.data(partition.nodes(root))
.enter().append("path")
.attr("d", arc)
.style("fill", function(d) { return color((d.children ? d : d.parent).name); })
.on("click", click);
function click(d) {
path.transition()
.duration(750)
.attrTween("d", arcTween(d));
}
});
d3.select(self.frameElement).style("height", height + "px");
// Interpolate the scales!
function arcTween(d) {
var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
yd = d3.interpolate(y.domain(), [d.y, 1]),
yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]);
return function(d, i) {
return i
? function(t) { return arc(d); }
: function(t) { x.domain(xd(t)); y.domain(yd(t)).range(yr(t)); return arc(d); };
};
}
</script>

Pie Chart Labels with D3.js and AngularJS

I'm new to D3. Trying to show "outside" labels with lines, in D3, similar to Bostock's pie chart here http://bl.ocks.org/dbuezas/9306799 I can't get the labels or lines to show up like Bostock's pie. The pie is working well though! Any help with my code, mainly the directive, would be appreciated!
HTML:
<div ng-controller="myControl">
<d3-pie-dir data="d3Data"></d3-pie-dir>
</div>
CSS:
path.slice{
stroke-width:2px;
}
polyline{
opacity: .3;
stroke: black;
stroke-width: 2px;
fill: none;
}
Controller:
inAng.controller('myControl', function ( $scope, $http ) {
var stack = [];
$http.get("/getAPIData").
success(function (data, status, headers, config) {
// formatting for easier D3 consumption
for(var i in data)
stack.push(data [i]);
$scope.d3Data = stack;
// looks something like $scope.d3Data = [{ name: 'Bill', score: 25}, { name: 'Pete', score: 50}]
}).
error(function (data, status, headers, config) {
$scope.stack = 'Error!';
});
});
And the problem is in the directive:
inAng.directive('d3PieDir', function () {
return {
restrict: 'E',
scope: {
data: '='
},
link: function (scope, element, attrs) {
scope.$watch('data', function(values) {
if(values) {
console.log('values from directive: ', values);
var width = 960,
height = 500,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.score;
});
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
values.forEach(function(d) {
d.score = +d.score;
});
var g = svg.selectAll(".arc")
.data(pie(values))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d) { return color(d.data.name); });
// **** Below is where it stops working! ****
var key = function(d){ return d.data.name; };
/* ------- PIE SLICES -------*/
var slice = svg.select(".slices").selectAll("path.slice")
.data(pie(values), key);
slice.enter()
.insert("path")
.style("fill", function(d) { return color(d.data.name); })
.attr("class", "slice");
slice
.transition().duration(1000)
.attrTween("d", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
return arc(interpolate(t));
};
})
slice.exit()
.remove();
/* ------- TEXT LABELS -------*/
var text = svg.select(".labels").selectAll("text")
.data(pie(values), key);
text.enter()
.append("text")
.attr("dy", ".35em")
.text(function(d) {
return d.data.name;
});
function midAngle(d){
return d.startAngle + (d.endAngle - d.startAngle)/2;
}
text.transition().duration(1000)
.attrTween("transform", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1);
return "translate("+ pos +")";
};
})
.styleTween("text-anchor", function(d){
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
return midAngle(d2) < Math.PI ? "start":"end";
};
});
text.exit()
.remove();
/* ------- SLICE TO TEXT POLYLINES -------*/
var polyline = svg.select(".lines").selectAll("polyline")
.data(pie(values), key);
polyline.enter()
.append("polyline");
polyline.transition().duration(1000)
.attrTween("points", function(d){
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
return [arc.centroid(d2), outerArc.centroid(d2), pos];
};
});
polyline.exit()
.remove();
}
})}
}});
You have two problems the first one is that you forgot to append these elements to your svg
svg.append("g")
.attr("class", "slices");
svg.append("g")
.attr("class", "labels");
svg.append("g")
.attr("class", "lines");
these are the g elements that d3 draws lines and labels on , so you need to put them after
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
,, the second issue is that you forgot to define outer arc ,,
var outerArc = d3.svg.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9);
which you use in your calculation for creating lines

Resources