D3 图表过渡要么获得正确的数字或宽度,但不能同时获得两者

D3 chart transition either gets right number or width, but not both

本文关键字:但不能 数字 D3      更新时间:2023-09-26

我刚拿起D3,开始玩条形图动画。我有 5 个柱,当我点击时过渡到 3 并返回。我可以:

  1. 将 5 根柱线变为 3 条形,然后返回 5 条形,而不会动态更改条形宽度,或者
  2. 具有动态变化的条形宽度,但只有 3 个柱线(通过注释掉 .enter() 和 .append())。

将不胜感激任何关于如何获得两者的帮助!完整文件在这里:

https://github.com/datapress/learningD3/blob/master/chart.html

            var sortOrder = false;
            d3.selectAll("rect")
              .on("click", function() {       
                sortOrder = !sortOrder
                var rectID = d3.select(this).attr("id");
                var dataset0 = [1, 2, 3, 4, 5];
                var dataset1 = [5, 1, 1];
                var dataset2 = [1, 5, 1];
                var dataset3 = [1, 1, 5];
                var dataset4 = [5, 5, 1];
                var dataset5 = [1, 5, 5];
                if (sortOrder) {
                    if (rectID == 0) { dataset = dataset1 };
                    if (rectID == 1) { dataset = dataset2 };
                    if (rectID == 2) { dataset = dataset3 };
                    if (rectID == 3) { dataset = dataset4 };
                    if (rectID == 4) { dataset = dataset5 };
                } else {
                    dataset = dataset0
                }
                xScale.domain(d3.range(dataset.length))
                yScale.domain([0, d3.max(dataset, function(d) { return d; })])
                svg.selectAll("rect")
                    .data(dataset)
                    .exit()
                    .remove()
                svg.selectAll("rect")
                    .data(dataset)
                    .enter()
                    .append("rect")
                    .transition()   
                    .duration(1000)  
                    .attr({
                        x: function(d, i) { return xScale(i); }, 
                        y: function(d) { return h - yScale(d); },
                        width: xScale.rangeBand(),
                        height: function(d) { return yScale(d); },
                        fill: function(d) { return "rgb(0, 0, " + (255 - Math.round(d) * 36) + ")"; }
                        });
                    });

这很直截了当,但这是您的代码修复以更新两者:

http://jsfiddle.net/TheMcMurder/r0ptsfLr/

注意:您没有遵循 d3 的进入、更新、退出方法。您有进入和退出,但对于页面上存在但需要使用新数据进行更改的栏,您在任何地方都没有隐式更新。

下面是一个简化的示例:

        var data =[45, 10]
        var data2 =[45, 10, 20, 25, 30, 45]


        /*The purpose of this JSfiddle is to show how enter, update, and exit works in d3js.  The data values above are the data. The image had three manually created black circles.  My update will resize them to the appropriate size (based on data) and change their color to blue.  All newly drawn objects will be turned green and any object that is exiting will be turned red.
        The transitions are delayed to make it easier to see.  No delay is needed for this to work.
        */
        //creating the svg so I can draw objects on it
        var svg = d3.select("body").append("svg")
            .attr("width", 500)
            .attr("height", 5000)
        //creating initial circle objects
        var circle1 = svg.append("circle")
            .attr("cx", 100)
            .attr("cy", 100)
            .attr("r", 25)
        // another circle object
        var circle2 = svg.append("circle")
            .attr("cx", 100)
            .attr("cy", 200)
            .attr("r", 25)

        // another circle object
        var circle3 = svg.append("circle")
            .attr("cx", 100)
            .attr("cy", 300)
            .attr("r", 25)

        setTimeout( function(){
            enter_update_exit(data)
        }, 2500 )

        setTimeout( function(){
            enter_update_exit(data2)
        }, 10000 )
        setTimeout( function(){
            enter_update_exit(data)
        }, 15000 )

        function enter_update_exit (data){

            var circle_array = svg.selectAll("circle")
                .data(data);

            //**********************************************************************************
            // Enter: all pieces of data that do not have a node to bind to. In this case where
            // there are already three circles ('nodes') there would have to be more than 3 
            // data points in our dataset to have enter run at all;
            //**********************************************************************************
            circle_array.enter()
                .append("circle")
                .attr("cx", 100)
                .attr("cy", function(d, i){
                    return (i + 1)*100
                })
                .attr("r", 0)
                .attr("fill", "#78AB46")
                .transition()
                .duration(1500)
                .attr("r", function (d){return d;});
            //**********************************************************************************
            // Update: Every node that is bound to data, in this case that is everything we've
            // entered and everything that has just been bound from the .data(data) bind.
            //**********************************************************************************
            circle_array.transition()
            .duration(1500)
            .delay(1500)
            .style('fill', 'steelblue')
            .attr('r', function (d){
                return d;
            });
            //**********************************************************************************
            // Exit: Every node ('circles') that exists in your selection that you don't have
            // bound data to
            //**********************************************************************************
            circle_array.exit()
            .transition().duration(1500).delay(1500)
            .style("fill", "red")
            .transition().duration(1500).delay(3000)
            .attr("r", 0).transition().remove();
        }

http://jsfiddle.net/TheMcMurder/H3HTe/

我希望这有所帮助!

相关文章: