Search code examples
d3.jsdonut-chart

D3.js Donut Graph Labels Getting Polytriangles Instead of Polylines


I have been working on creating a donut chart using D3.js. I have been following the example laid out HERE. Everything has gone great until I reach the section about the polylines drawn from the donut slices to the text labels. I have copied the example code exactly and while in their example they get nice lines I get triangles as shown HERE.

So, besides it not working correctly I must admit I don't really understand the polyline piece of the code. This makes it so I don't even know where to start in looking for the cause of the issue. Below is the polyline drawing code from my project. Any help or insight is appreciated.

var polyline = chart.select(".lines").selectAll("polyline")
                        .data(pie(data), 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();

EDIT

So, as per usual once I gave in and asked this question I found out what was wrong. In the example I linked to they use a stylesheet to set the fill property to none. While that works I would rather it stayed in the D3 code. For any interested this is what the code would look like.

var polyline = chart.select(".lines").selectAll("polyline")
                        .data(pie(data), key);

                    polyline.enter()
                        .append("polyline")
                        .style("fill", "none")
                        .style("stroke-width", "2px")
                        .style("stroke", "black")
                        .style("opacity", "0.4");

                    polyline.transition().duration(500)
                        .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();

Solution

  • So, as per usual once I gave in and asked this question I found out what was wrong. In the example I linked to they use a stylesheet to set the fill property to none. While that works I would rather it stayed in the D3 code. For any interested this is what the code would look like.

    var polyline = chart.select(".lines").selectAll("polyline")
                            .data(pie(data), key);
    
                        polyline.enter()
                            .append("polyline")
                            .style("fill", "none")
                            .style("stroke-width", "2px")
                            .style("stroke", "black")
                            .style("opacity", "0.4");
    
                        polyline.transition().duration(500)
                            .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();