d3.js带有角度/水平标签的饼图 [英] d3.js pie chart with angled/horizontal labels

查看:483
本文介绍了d3.js带有角度/水平标签的饼图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做一个饼图嘲笑。我需要尝试匹配的设计,以使标签挤出与水平线附加到切片蜱。这可能吗?

I'm working on a pie chart mock. That I need to try and match the designs to have the label extruding out with a horizontal line attached to the slice ticks. Is this possible? It would be a bonus to have the black dots form on the segments.

http://jsfiddle.net/BxLHd/15/

这里是刻度线的代码。是否会创建另一组相交的线?

Here is the code for the tick marks. Would it be a case of creating another set of lines that intersect?

                        //draw tick marks
                        var label_group = d3.select('#'+pieId+' .label_group');
                        lines = label_group.selectAll("line").data(filteredData);
                        lines.enter().append("svg:line")
                                .attr("x1", 0)
                                .attr("x2", 0)
                                .attr("y1", function(d){
                                    if(d.value > threshold){
                                        return -that.r-3;
                                    }else{
                                        return -that.r;
                                    }
                                })
                                .attr("y2", function(d){
                                    if(d.value > threshold){
                                        return -that.r-8;
                                    }
                                    else{                                   
                                        return -that.r;
                                    }
                                })
                                .attr("stroke", "gray")
                                .attr("transform", function(d) {
                                        return "rotate(" + (d.startAngle+d.endAngle)/2 * (180/Math.PI) + ")";
                                });

                        lines.transition()
                                .duration(this.tweenDuration)
                                .attr("transform", function(d) {
                                        return "rotate(" + (d.startAngle+d.endAngle)/2 * (180/Math.PI) + ")";
                                });

                        lines.exit().remove();


推荐答案

这在一个jQuery插件。现在可以开发多个带有这些标签的饼图。

To conclude I've wrapped the very latest code for this in a jquery plugin. Its now possible to develop multiple pie charts with these labels.

最新代码 - ** http://jsfiddle.net/Qh9X5/1336/ - 在退出时正确移除标签。

LATEST CODE - ** http://jsfiddle.net/Qh9X5/1336/ - removes label properly on exit.

$(document).ready(function() {


            (function( $ ){
                var methods = {
                    el: "",
                    init : function(options) {
                        var clone = jQuery.extend(true, {}, options["data"]);

                        methods.el = this;          
                        methods.setup(clone, options["width"], options["height"], options["r"], options["ir"]);
                    },
                    getArc: function(radius, innerradius){
                        var arc = d3.svg.arc()
                            .innerRadius(innerradius)
                            .outerRadius(radius);

                        return arc;
                    },
                    setup: function(dataset, w, h, r, ir){

                        var padding = 80;

                        this.width = w;
                        this.height = h;
                        this.radius = r
                        this.innerradius = ir;

                        this.color = d3.scale.category20();

                        this.pie = d3.layout.pie()
                            .sort(null)
                            .value(function(d) { return d.total; });

                        this.arc = this.getArc(this.radius, this.innerradius);

                        this.svg = d3.select(methods.el["selector"]).append("svg")
                            .attr("width", this.width + padding)
                            .attr("height", this.height + padding)
                            .append("g")
                                .attr("class", "piechart")
                                .attr("transform", "translate(" + ((this.width/2) + (padding/2)) + "," + ((this.height/2) + (padding/2)) + ")");                

                        this.segments = this.svg.append("g")
                                .attr("class", "segments");

                        this.labels = this.svg.append("g")
                                .attr("class", "labels");

                        this.pointers = this.svg.append("g")
                                .attr("class", "pointers");


                    },
                    oldPieData: "",
                    pieTween: function(r, ir, d, i){
                        var that = this;

                        var theOldDataInPie = methods.oldPieData;
                        // Interpolate the arcs in data space

                        var s0;
                        var e0;

                        if(theOldDataInPie[i]){
                                s0 = theOldDataInPie[i].startAngle;
                                e0 = theOldDataInPie[i].endAngle;
                        } else if (!(theOldDataInPie[i]) && theOldDataInPie[i-1]) {
                                s0 = theOldDataInPie[i-1].endAngle;
                                e0 = theOldDataInPie[i-1].endAngle;
                        } else if(!(theOldDataInPie[i-1]) && theOldDataInPie.length > 0){
                                s0 = theOldDataInPie[theOldDataInPie.length-1].endAngle;
                                e0 = theOldDataInPie[theOldDataInPie.length-1].endAngle;
                        } else {
                                s0 = 0;
                                e0 = 0;
                        }

                        var i = d3.interpolate({startAngle: s0, endAngle: e0}, {startAngle: d.startAngle, endAngle: d.endAngle});

                        return function(t) {
                                var b = i(t);
                                return methods.getArc(r, ir)(b);
                        };
                    },
                    removePieTween: function(r, ir, d, i) {             
                        var that = this;
                        s0 = 2 * Math.PI;
                        e0 = 2 * Math.PI;
                        var i = d3.interpolate({startAngle: d.startAngle, endAngle: d.endAngle}, {startAngle: s0, endAngle: e0});

                        return function(t) {
                                var b = i(t);
                                return methods.getArc(r, ir)(b);
                        };
                    },
                    update: function(dataSet){
                        var that = this;

                        methods.el = this;
                        var r = $(methods.el["selector"]).data("r");
                        var ir = $(methods.el["selector"]).data("ir");

                        methods.svg = d3.select(methods.el["selector"] + " .piechart");

                        methods.segments = d3.select(methods.el["selector"] + " .segments");
                        methods.labels = d3.select(methods.el["selector"] + " .labels");
                        methods.pointers = d3.select(methods.el["selector"] + " .pointers");

                        dataSet.forEach(function(d) {
                            d.total = +d.value;
                        });                     

                        this.piedata = methods.pie(dataSet);

                        //__slices
                        this.path = methods.segments.selectAll("path.pie")
                            .data(this.piedata);

                        this.path.enter().append("path")
                            .attr("class", "pie")
                            .attr("fill", function(d, i) {
                                return methods.color(i); 
                            })
                            .transition()
                                .duration(300)
                                .attrTween("d", function(d, i) {
                                    return methods.pieTween(r, ir, d, i); 
                                });

                        this.path
                                .transition()
                                .duration(300)
                                .attrTween("d", function(d, i) {
                                    return methods.pieTween(r, ir, d, i); 
                                });

                        this.path.exit()
                                .transition()
                                .duration(300)
                                .attrTween("d", function(d, i) {
                                    return methods.removePieTween(r, ir, d, i); 
                                })
                                .remove();    
                        //__slices


                        //__labels  
                        var labels = methods.labels.selectAll("text")
                            .data(this.piedata);

                        labels.enter()
                            .append("text")
                            .attr("text-anchor", "middle")


                        labels
                            .attr("x", function(d) {
                                var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2;
                                d.cx = Math.cos(a) * (ir+((r-ir)/2));
                                return d.x = Math.cos(a) * (r + 20);
                            })
                            .attr("y", function(d) {
                                var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2;
                                d.cy = Math.sin(a) * (ir+((r-ir)/2));
                                return d.y = Math.sin(a) * (r + 20);
                            })
                            .text(function(d) {
                                return d.data.label; 
                            })
                            .each(function(d) {
                                var bbox = this.getBBox();
                                d.sx = d.x - bbox.width/2 - 2;
                                d.ox = d.x + bbox.width/2 + 2;
                                d.sy = d.oy = d.y + 5;
                            })
                            .transition()
                                .duration(300)

                        labels
                            .transition()
                            .duration(300)      

                        labels.exit()
                            .transition()
                            .duration(300)
                        //__labels


                        //__pointers
                        methods.pointers.append("defs").append("marker")
                            .attr("id", "circ")
                            .attr("markerWidth", 6)
                            .attr("markerHeight", 6)
                            .attr("refX", 3)
                            .attr("refY", 3)
                            .append("circle")
                            .attr("cx", 3)
                            .attr("cy", 3)
                            .attr("r", 3);

                        var pointers = methods.pointers.selectAll("path.pointer")
                            .data(this.piedata);

                        pointers.enter()
                            .append("path")
                            .attr("class", "pointer")
                            .style("fill", "none")
                            .style("stroke", "black")
                            .attr("marker-end", "url(#circ)");

                        pointers
                            .attr("d", function(d) {
                                if(d.cx > d.ox) {
                                    return "M" + d.sx + "," + d.sy + "L" + d.ox + "," + d.oy + " " + d.cx + "," + d.cy;
                                } else {
                                    return "M" + d.ox + "," + d.oy + "L" + d.sx + "," + d.sy + " " + d.cx + "," + d.cy;
                                }
                            })
                            .transition()
                                .duration(300)

                        pointers
                            .transition()
                            .duration(300)      

                        pointers.exit()
                            .transition()
                            .duration(300)

                        //__pointers

                        this.oldPieData = this.piedata;

                    }
                };

                $.fn.piechart = function(methodOrOptions) {
                    if ( methods[methodOrOptions] ) {
                        return methods[ methodOrOptions ].apply( this, Array.prototype.slice.call( arguments, 1 ));
                    } else if ( typeof methodOrOptions === 'object' || ! methodOrOptions ) {
                        // Default to "init"
                        return methods.init.apply( this, arguments );
                    } else {
                        $.error( 'Method ' +  methodOrOptions + ' does not exist' );
                    }    
                };

            })(jQuery);



            var dataCharts = [
                {
                    "data": [
                        {
                            "segments": [
                                {
                                    "label": "apple",
                                    "value": 53245
                                },
                                {
                                    "label": "cherry",
                                    "value": 145
                                },
                                {
                                    "label": "pear",
                                    "value": 2245
                                },
                                {
                                    "label": "bananana",
                                    "value": 15325
                                }                           
                            ]
                        }
                    ]
                },
                {
                    "data": [
                        {
                            "segments": [
                                {
                                    "label": "milk",
                                    "value": 532
                                },
                                {
                                    "label": "cheese",
                                    "value": 145
                                },
                                {
                                    "label": "grapes",
                                    "value": 22
                                }
                            ]
                        }
                    ]
                },
                {
                    "data": [
                        {
                            "segments": [
                                {
                                    "label": "pineapple",
                                    "value": 1532
                                },
                                {
                                    "label": "orange",
                                    "value": 1435
                                },
                                {
                                    "label": "grapes",
                                    "value": 22
                                }               
                            ]
                        }
                    ]
                },
                {
                    "data": [
                        {
                            "segments": [
                                {
                                    "label": "lemons",
                                    "value": 133
                                },
                                {
                                    "label": "mango",
                                    "value": 435
                                },
                                {
                                    "label": "melon",
                                    "value": 2122
                                }               
                            ]
                        }
                    ]
                }            
            ];

            var clone = jQuery.extend(true, {}, dataCharts);

                //__invoke concentric
                $('[data-role="piechart"]').each(function(index) {
                    var selector = "piechart"+index;

                    $(this).attr("id", selector);

                    var options = {
                        data: clone[0].data,
                        width: $(this).data("width"),
                        height: $(this).data("height"),
                        r: $(this).data("r"),
                        ir: $(this).data("ir")
                    }

                    $("#"+selector).piechart(options);
                    $("#"+selector).piechart('update', clone[0].data[0].segments);
                });


            $(".testers a").on( "click", function(e) {
                e.preventDefault();

                var clone = jQuery.extend(true, {}, dataCharts);

                var min = 0;
                var max = 3;

                //__invoke pie chart
                $('[data-role="piechart"]').each(function(index) {
                    pos = Math.floor(Math.random() * (max - min + 1)) + min;
                    $("#"+$(this).attr("id")).piechart('update', clone[pos].data[0].segments);
                });

            }); 

});

这篇关于d3.js带有角度/水平标签的饼图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆