与动画相反,圆弧补间是捕捉

时间:2014-01-24 17:17:40

标签: javascript jquery d3.js

我一直在制作一个带有发芽光谱的饼图。

我有一个演示工作,但是补间动画正在捕捉,而不是平滑地制作动画。如果有人可以帮助增强它,那就太好了,所以它可以动画而不是拍摄周围的弧线。

http://jsfiddle.net/BxLHd/9/

我已经对选择器阈值进行了硬编码。弧线似乎没有正确补间 - 似乎是快速的。

var arcGenerator = {
    radius: 100,
    oldData: "",
    init: function(data){
        var clone = jQuery.extend(true, {}, data);
        this.oldData = this.setData(clone, false);
        this.setup(this.setData(data, true));           
    },
    update: function(data){
        var clone = jQuery.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(".arcchart");
        that.generateArcs(chart, data);
    },  
    setData: function(data, isSorted){

        var diameter = 2 * Math.PI * this.radius;

        var localData = new Array();

        var innerPieSliceTotal = 0;
        for (x in data) {
            innerPieSliceTotal += data[x].value;
        }

        var displacement = 0;
        var oldBatchLength = 0;

        if(isSorted){
            data.sort(function(a, b) {  
                return b.value - a.value;
            });
        }           

        $.each(data, function(index, value) {               
            var riseLevels = value.riselevels;
            var machineType = value.label;              
            var innerPieSliceValue = value.value;

            var ratioToWorkWith = innerPieSliceValue/innerPieSliceTotal;
            var riseLevelCount = riseLevels.length;

            if(oldBatchLength !=undefined){             
                displacement+=oldBatchLength;
            }

            var arcBatchLength = (2*ratioToWorkWith)*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;
                    riseLevels[ri]["machineType"] = machineType;                    
                });

            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;

        //append previous value to it.          
        $.each(data, function(index, value) {               
            data[index]["previousEndAngle"] = that.oldData[index].endAngle; 
        });     

        var arcpaths = chart.selectAll("path")
                .data(data);

            arcpaths.enter().append("svg:path")
                .attr("class", function(d, i){
                    return d.machineType;
                })  
                .style("fill", function(d, i){
                    return d.color;
                })
                .transition()
                .ease("elastic")
                .duration(750)
                .attrTween("d", arcTween);

            arcpaths.transition()
                .ease("elastic")
                .duration(750)
                .attrTween("d",arcTween);

            arcpaths.exit().transition()
                .ease("bounce")
                .duration(750)
                .attrTween("d", arcTween)
                .remove();  

        function arcTween(b) {
            var i = d3.interpolate({value: b.endAngle-0.1}, b);

            return function(t) {
                return that.getArc()(i(t));
            };
        }           
    },
    setup: function(data){      
        var chart = d3.select("#threshold").append("svg:svg")
                .attr("class", "chart")
                .attr("width", 420)
                .attr("height", 420)
                    .append("svg:g")
                    .attr("class", "arcchart")
                    .attr("transform", "translate(200,200)");

        this.generateArcs(chart, data);     
    },
    getArc: function(){
        var that = this;

        var arc = d3.svg.arc()
                .innerRadius(that.radius)
                .outerRadius(function(d){
                    var maxHeight = 100;
                    var ratio = (d.height/maxHeight * 100)+that.radius;
                    return ratio;
                })
                .startAngle(function(d, i){
                    return d.startAngle;
                })
                .endAngle(function(d, i){
                    return d.endAngle;
                });

        return arc;
    }
}

1 个答案:

答案 0 :(得分:1)

您的arcTween函数在错误的值之间进行插值。在这种情况下,您需要的是数据元素与endAnglepreviousEndAngle(正如您已经在计算)和未修改元素之间的插值。以下代码实现了这一点。

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

完整示例here