代码之家  ›  专栏  ›  技术社区  ›  The Old County

d3js弧高粗差

  •  0
  • The Old County  · 技术社区  · 7 年前

    我试着在这张图表中不同弧的高度之间

    J桥 http://jsfiddle.net/0ht35rpb/193/

    我看过这个例子,但不确定如何开始实现它。

    d3 how to tween inner radius for pie chart

    我在各种特温数学课程中见过这个例子。 http://andyshora.com/tweening-shapes-paths-d3-js.html

    var $this = $("#chart");
    
    
            var data = [{
                  "label": "Overall Stress",
                  "value": 89
                },{
                  "label": "Emotional Stress",
                  "value": 1
                },{
                  "label": "Behavioural difficulties",
                  "value": 29
                },{
                  "label": "hyperactivity and concetration",
                  "value": 89
                },{
                  "label": "Getting along with others",
                  "value": 19
                },{
                  "label": "Keen and helpful behaviour",
                  "value": 45
                }];
    
    
            var w  = 350;
            var h  = 350;
    
            function colores_google(n) {
                var colores_g = ["#f7b363", "#448875", "#c12f39", "#2b2d39", "#f8dd2f", "#c12fff"];
                return colores_g[n % colores_g.length];
            }
    
            var arcGenerator = {
                radius: 70,
                oldData: "",
                init: function(el, data, w, h){
    
                    var stardata = [
                        {
                            "segments": data
                        }
                    ];
    
                    this.el = el;
    
                    var clone = $.extend(true, {}, stardata);
                    this.oldData = this.setData(clone, false);
                    this.setup(el, this.setData(stardata, true), w, h);         
                },
                update: function(data){
                    var clone = $.extend(true, {}, data);           
                    this.animate(this.setData(data, true));         
                    this.oldData = this.setData(clone, false);
                },
                animate: function(data){
                    var that = this;
    
                    var chart = d3.select(this.el);
                    that.generateArcs(chart, data);
                },  
                setData: function(data, isSorted){
    
                    var diameter = 2 * Math.PI * this.radius;
    
                    var localData = new Array();
    
                    var displacement = 0;
                    var oldBatchLength = 0;
    
                    $.each(data, function(index, value) {               
                        var riseLevels = value.segments;
    
                        var riseLevelCount = riseLevels.length;
    
                        if(oldBatchLength !=undefined){             
                            displacement+=oldBatchLength;
                        }
    
                        var arcBatchLength = 2*Math.PI;
                        var arcPartition = arcBatchLength/riseLevelCount;
    
                            $.each(riseLevels, function( ri, value ) {
                                var startAngle = (ri*arcPartition);
                                var endAngle = ((ri+1)*arcPartition);
    
                                if(index!=0){
                                    startAngle+=displacement;
                                    endAngle+=displacement;
                                }
    
                                riseLevels[ri]["startAngle"] = startAngle;
                                riseLevels[ri]["endAngle"] = endAngle;                  
                            });
    
                        oldBatchLength = arcBatchLength;
    
                        localData.push(riseLevels);
                    });
    
                    var finalArray = new Array();
    
                    $.each(localData, function(index, value) {
                        $.each(localData[index], function(i, v) {
                            finalArray.push(v);
                        });
                    });
    
                    return finalArray;      
                },
                generateArcs: function(chart, data){            
                    var that = this;
    
                    //_arc paths
    
                    //append previous value to it.          
                    $.each(data, function(index, value) {
                        if(that.oldData[index] != undefined){
                            data[index]["previousEndAngle"] = that.oldData[index].endAngle;
                        }
                        else{
                            data[index]["previousEndAngle"] = 0;
                        }
                    });     
    
                    var arcpaths = that.arcpaths.selectAll("path")
                            .data(data);
    
                        arcpaths.enter().append("svg:path")
                            .style("fill", function(d, i){
                                return colores_google(i);
                            })
                            .transition()
                            .ease(d3.easeElastic)      
                            .duration(750)
                            .attrTween("d", arcTween);               
    
                        arcpaths.transition()
                             .ease(d3.easeElastic)                  
                            .style("fill", function(d, i){
                                return colores_google(i);
                            })
                            .duration(750)
                            .attrTween("d",arcTween);
    
                        arcpaths.exit().transition()
                            .ease(d3.easeBounce)
                            .duration(750)
                            .attrTween("d", arcTween)
                            .remove();
    
                    function arcTween(b) {
    
                        var prev = JSON.parse(JSON.stringify(b));
                        prev.endAngle = b.previousEndAngle;
                        var i = d3.interpolate(prev, b);
    
                        return function(t) {
                            return that.getArc()(i(t));
                        };
                    }
                    //_arc paths
    
                    var r = that.radius + 40;
                    var ir = that.radius - 30;
    
                    var legendHeight = this.legendPaddingTop;
                    var ySpace = 18;
                    var labelPadding = 3;
    
                    //draw labels legends                   
                    var labels = that.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) + labelPadding;
                        })
                        .attr("text-anchor", function(d) {
                          return "start";
                        })
                        .text(function(d) {
                          return d.label;
                        });
    
                    labels.exit().remove();
    
    
                    var legend = that.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();
    
                    //reset legend height
                    //console.log("optimum height for legend", legendHeight);
                    $this.find('.legend').attr("height", legendHeight);
    
    
                    /*
                        //__labels  
                        var starlabels = that.starlabels.selectAll("text")
                            .data(data);
    
                        starlabels.enter()
                            .append("text")
                            .attr("text-anchor", "middle")
    
    
                        starlabels.text(function(d) {
                                return d.label; 
                            })
                            .each(function(d) {
                                var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2;
                                d.cx = Math.cos(a) * (ir+((r-ir)/2));
                                d.cy = Math.sin(a) * (ir+((r-ir)/2));
                                d.x = d.x || Math.cos(a) * (r + 20);
                                d.y = d.y || Math.sin(a) * (r + 20);
                                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)
                            .attr("x", function(d) {
                                var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/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;
                                return d.y = Math.sin(a) * (r + 20);
                            });
    
    
                        starlabels.exit().remove();
                        //__labels            
    
    
                        //__pointers
                        that.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)
                            .style("fill", "#005a70");
    
                        var pointers = that.pointers.selectAll("path.pointer")
                            .data(data);
    
                        pointers.enter()
                            .append("path")
                            .attr("class", "pointer")
                            .style("fill", "none")
                            .style("stroke", "#005a70")
                            .attr("marker-end", "url(#circ)");
    
                        pointers
                            .transition()
                                .duration(300)
                            .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;
                                }
                            });     
    
                        pointers.exit().remove();                               
                        //__pointers
                    */                                 
    
                },
                setup: function(el, data, w, h){        
                    var chart = d3.select(el).append("svg")
                            .attr("class", "chart")
                            .attr("width", w)
                            .attr("height", h)
    
                    var arcchart = chart.append("g")
                                .attr("class", "starchart")
                                .attr("transform", "translate("+w/4+","+h/2+")");
    
                    this.arcpaths = arcchart.append("g")
                        .attr("class", "arcpaths");
    
                    this.starlabels = arcchart.append("g")
                        .attr("class", "labels");
    
                    this.pointers = arcchart.append("g")
                        .attr("class", "pointer");
    
                    var margin = 25;
                    var padding = 15;
    
                    this.legendPaddingTop = 30;
    
                    var legend = chart.append("g")
                        .attr("class", "legend")
                        .attr("width", w/3)
                        .attr("height", h - 50)
                        .attr("transform", "translate(" + (w-20) + "," + (h/4) + ")");  
    
                    this.label_group = legend.append("g")
                        .attr("class", "label_group")
                        .attr("transform", "translate(" + (-(w / 3) + 20) + "," + 0 + ")");
    
                    this.legend_group = legend.append("g")
                        .attr("class", "legend_group")
                        .attr("transform", "translate(" + (-(w / 3) - 100) + "," + 0 + ")");
    
    
                    var radiusControl = 16;
    
                    this.dataset = "big";//more than 2 results
                    if(data.length <=2){
                        radiusControl = 65;//make the radius smaller to compromise with there being less results
                        this.dataset = "small";
                    }
    
                    this.radius = w/4 - radiusControl;
    
                    this.generateArcs(chart, data); 
                },
                getArc: function(){
                    var that = this;
    
                    var arc = d3.arc()
                            .innerRadius(function(d, i){
                                var threshold = 50;
                                if(that.dataset == "small"){
                                    threshold = 20;
                                }
    
                                return that.radius-threshold;//negative makes it deeper
                            })
                            .outerRadius(function(d){
                                var maxHeight = 120;
                                var ratio = (d.value/maxHeight * 100)+that.radius;
                                return ratio;
                            })
                            .startAngle(function(d, i){
                                return d.startAngle;
                            })
                            .endAngle(function(d, i){
                                return d.endAngle;
                            });
    
                    return arc;
                }
            }
    
            arcGenerator.init($this[0], data, w, h);
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   Cyril Cherian    7 年前

    在你的 attrTween 函数而不是插值角度插值值:

    function arcTween(b) {
    
        var prev = JSON.parse(JSON.stringify(b));
        prev.endAngle = b.previousEndAngle; <-- incorrect
        var i = d3.interpolate(prev, b);
    

    function arcTween(b) {
    
            var prev = JSON.parse(JSON.stringify(b));
            prev.value = 0;
            var i = d3.interpolate(prev, b);
    

    工作代码 here