d3.js - 多个元素上的补间数字

时间:2014-11-16 02:22:51

标签: d3.js transition tween

我已经建立了一个包含一系列“小倍数”的图表,每个图表代表完成的百分比,按行和列排列。每行都有一个不同的数字代表“完整”。

您可以在此小提琴中查看图表:http://jsfiddle.net/rolfsf/Lhnm9a9m/

我正在使用过渡来将条形从0增加到x%宽度。

我还想使用转换来显示从0开始递增的每个度量的实际计数(例如,17个中的10个)。

我使用文本补间功能将所有数字从0递增,但所有指标都停在相同的计数,而不是正确的计数。

我必须要么在补间中使用错误的数据,要么将补间放在脚本的错误部分......但我无法弄清楚问题出在哪里。

如何让数字正确递增?

我的数据如下所示:

var sets = [

        {"title": "Set-1", "count": 17, "measures": [10, 13, 16, 14]},
        {"title": "Set-2", "count": 23, "measures": [12, 18, 19, 23]},
        {"title": "Set-3", "count": 25, "measures": [19, 22, 23, 20]},
        {"title": "Set-4", "count": 4, "measures": [4, 4, 4, 4]},
        {"title": "Set-5", "count": 8, "measures": [5, 7, 8, 6]}
];

图表的调用方式如下:

d3  .select('#overview-graph')
    .datum(sets)
    .call(relativeCompletionChart()
    //options
    );

,这是可重复使用的图表脚本:

function relativeCompletionChart() {
    var width = 1200,
        margin = {top: 16, right: 16, bottom: 16, left: 16},
        onSetMouseOver = null,
        onSetClick = null;

    function chart(selection) {
        selection.each(function(data) {
            var titleColWidth = 0.3*width,
                setHeight = 24,
                barHeight = 22,
                setCount = data.length,
                colCount = data[0].measures.length,
                colWidth = (width - titleColWidth)/colCount,
                rangeWidth = colWidth - 4,
                height = ((setHeight * setCount) + margin.top + margin.bottom);


            var svg = d3.select(this)
                        .append("svg")
                        .attr("width", width)
                        .attr("height", height)
                        .attr("viewBox", "0 0 " + width + " " + height )
                        .attr("preserveAspectRatio", "xMidYMin meet");

            svg         .append('rect')
                        .attr("x", 0)
                        .attr('y', 0)
                        .attr('height', height)
                        .attr('width', width)
                        .attr('class', 'chart-bg');

            /**
            * Tween functions
            */
            function tweenText( newValue ) {
                return function() {
                  // get current value as starting point for tween animation
                  var currentValue = +this.textContent;
                  // create interpolator and do not show nasty floating numbers
                  var i = d3.interpolateRound( currentValue, newValue );

                  return function(t) {
                    this.textContent = i(t);
                  };
                }
            }

            function update(data) {

                var set = svg.selectAll("g.set")
                    .data(data);

                set.exit().remove();

                var setEnter = set
                        .enter().append("g")
                    .attr("class", "set")
                    .attr('transform', function (d, i) {
                        return 'translate(0, ' + (margin.top + i*setHeight) + ')';
                    });

                set.append("text")
                        .attr("class", "title")
                        .attr("x", (titleColWidth - 80))
                        .attr("y", 16)
                        .attr("text-anchor", "end")
                        .text(function (d){return d.title;});

                set.append("text")
                        .attr("class", "count")
                        .attr("x", (titleColWidth - 32))
                        .attr("y", 16)
                        .attr("text-anchor", "end")
                        .text(function (d){return d.count;});


                var ranges = set.selectAll("rect.range")
                        .data(function(d, i){return d.measures})
                            .enter().append('rect')
                        .attr("class", "range")
                        .attr("x",2)
                        .attr("y",0)
                        .attr('rx', 2)
                        .attr('ry', 2)
                        .attr("width", rangeWidth)
                        .attr("height",barHeight)
                        .attr("fill", "#CCCCCC")
                        .attr('transform', function (d, i) {
                            return 'translate(' + (titleColWidth + i*colWidth) + ', 0)';
                        });

                var measures = set.selectAll("rect.measure")
                        .data(function(d, i){return d.measures})
                            .enter().append('rect')
                        .attr("class", "measure")
                        .attr('rx', 2)
                        .attr('ry', 2)
                        .attr("x",2)
                        .attr("y",0)
                        .attr("width", 1)
                        .attr("height",barHeight)
                        .attr('transform', function (d, i) {
                            return 'translate(' + (titleColWidth + i*colWidth) + ', 0)';
                        });

                var markers = set.selectAll("line.marker")
                        .data(function(d, i){return d.measures})
                            .enter().append('line')
                        .attr("class", "marker")
                        .attr('x1', 2)
                        .attr('y1', 0)
                        .attr("x2",2)
                        .attr("y2",barHeight)
                        .attr('transform', function (d, i) {
                            return 'translate(' + (titleColWidth + i*colWidth) + ', 0)';
                        });

                var values = set.selectAll("text.value")     
                        .data(function(d, i){return d.measures})
                            .enter().append('text')
                        .text('0')
                        .attr("class", "value")
                        .attr("x", 8)
                        .attr("y", 16)
                        .attr("text-anchor", "start")
                        .attr('transform', function (d, i) {
                            return 'translate(' + (titleColWidth + i*colWidth) + ', 0)';
                        });


                //update widths
                set.selectAll("rect.measure")
                    .transition()
                    .duration(1000)
                    .delay(function(d, i) { return i * 20; })
                    .attr("width", function(d, i) { return d3.round((d/d3.select(this.parentNode).datum().count)*rangeWidth);});

                set.selectAll("line.marker")
                    .transition()
                    .duration(1000)
                    .delay(function(d, i) { return i * 20; })
                    .attr("x1", function(d, i) { return d3.round((d/d3.select(this.parentNode).datum().count)*rangeWidth + 1);})
                    .attr("x2", function(d, i) { return d3.round((d/d3.select(this.parentNode).datum().count)*rangeWidth + 1);});

                set.selectAll('text.value')
                    .transition()
                    .duration(1000)
                    .tween( 'text', function() {
                        // get current value as starting point for tween animation
                        var currentValue = +this.textContent;
                        // create interpolator and do not show nasty floating numbers
                        var interpolator = d3.interpolateRound( currentValue, 10 );

                        // this returned function will be called a couple
                        // of times to animate anything you want inside
                        // of your custom tween
                        return function( t ) {
                            // set new value to current text element
                            this.textContent = interpolator(t) + '/' + d3.select(this.parentNode).datum().count;
                        };
                    });                                
            }

            update(data);
        });

    }


    chart.width = function(_) {
        if (!arguments.length) return width;
        width = _;
        return chart;
    };

    chart.onSetClick = function(_) {
        if (!arguments.length) return onSetClick;
        onSetClick = _;
        return chart;
    };

    chart.onSetMouseOver = function(_) {
        if (!arguments.length) return onSetMouseOver;
        onSetMouseOver = _;
        return chart;
    };


    return chart;
 }

此处提取补间的相关代码:

                    set.selectAll('text.value')
                    .transition()
                    .duration(1000)
                    .tween( 'text', function() {
                        // get current value as starting point for tween animation
                        var currentValue = +this.textContent;
                        // create interpolator and do not show nasty floating numbers
                        var interpolator = d3.interpolateRound( currentValue, 10 );

                        // this returned function will be called a couple
                        // of times to animate anything you want inside
                        // of your custom tween
                        return function( t ) {
                            // set new value to current text element
                            this.textContent = interpolator(t) + '/' + d3.select(this.parentNode).datum().count;
                        };
                    });       

虽然我在脚本中也有一个未使用的辅助函数,但我无法工作:

           /**
            * Tween functions
            */
            function tweenText( newValue ) {
                return function() {
                  // get current value as starting point for tween animation
                  var currentValue = +this.textContent;
                  // create interpolator and do not show nasty floating numbers
                  var i = d3.interpolateRound( currentValue, newValue );

                  return function(t) {
                    this.textContent = i(t);
                  };
                }
            }                       

0 个答案:

没有答案