javascript - d3js 弧高补间

标签 javascript d3.js

我正在尝试调整此图表中各种弧线的高度

jsfiddle 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);

最佳答案

在您的 attrTween 函数中,不是插值 Angular 而是插值值:

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

关于javascript - d3js 弧高补间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46535247/

相关文章:

javascript - 在 React Native 中嵌入 Python/C++ 代码?

javascript - 为什么执行函数不起作用?

javascript - 同步 Javascript 和 PHP

javascript - 使用D3生成SVG饼图如何垂直对齐文本

javascript - 我的个人资料图片返回时带有 Javascript SDK 开放图 api 的参数。如何获得以 .JPG 结尾的直接网址?

javascript - Google Analytics 强制 HTTPS 以防止 307 内部重定向

javascript - 在 x 轴上带有范围选择器的 d3 条形图(如 dygraphs)

d3.js - 如何增加绘图面积图的宽度和高度

javascript - 如何在 HTML 中获取文件名并在 D3.js (javascript) 中使用它?

javascript - 在d3中如何实现这种过渡效果呢?