简体   繁体   English

如何在D3中的条形图更新数据之间转换?

[英]How to transition between updated data of bar chart, in d3?

I'm trying to get an understanding of transitions in bar charts using D3. 我试图了解使用D3的条形图中的过渡。 What I'm doing now is updating the chart between two different data sets. 我现在正在做的是更新两个不同数据集之间的图表。 I have a transition included but it's starting from the the bottom of the axis rather than transitioning between the two. 我包含一个过渡,但它是从轴的底部开始的,而不是在两者之间过渡。 My goal is to have it transition between the two and later change the colors. 我的目标是让它在两者之间过渡,然后再更改颜色。 I'm using this helpful example for understanding updated data (my snippet is not much different). 我正在使用这个有用的示例来了解更新的数据(我的代码段差别不大)。 Thank you for taking a look. 感谢您的关注。

var bothData = [
{
    "year": "2014",
    "product": "Books & DVDs",
    "purchase": "0.5"
    },
    {
    "year": "2002",
    "product": "Books & DVDs",
    "purchase": "10"
    },
    {
    "year": "2014",
    "product": "Beer & Wine",
    "purchase": "7"
    },
    {
    "year": "2002",
    "product": "Beer & Wine",
    "purchase": "3"
    },
    {
    "year": "2014",
    "product": "Food",
    "purchase": "12"
    },
    {
    "year": "2002",
    "product": "Food",
    "purchase": "12"
    },
    {
    "year": "2014",
    "product": "Home Supplies",
    "purchase": "7"
    },
    {
    "year": "2002",
    "product": "Home Supplies",
    "purchase": "6"
    }
    ];

    var data2002 = [];
    var data2014 = [];

    for(var i = 0; i < bothData.length; i++){
        if(bothData[i]["year"] === "2002"){
            data2002.push(bothData[i]);
        }else{
            data2014.push(bothData[i]);
        }
    }

    function change(value){

        if(value === '2002'){
            update(data2002);
        }else if(value === '2014'){
            update(data2014);
        }
    }

    function update(data){
        xChart.domain(data.map(function(d){ return d.product; }) );
        yChart.domain( [0, d3.max(data, function(d){ return + d.purchase; })] );

        var barWidth = width / data.length;

        var bars = chart.selectAll(".bar")
                .remove()
                .exit()
                .data(data, function(d){ return d.purchase; })
                .enter()
                .append("rect")
                .attr("class", "bar")
                .attr("x", function(d, i){ return i * barWidth + 1 })
                .attr("y",500)
                .attr("height",0)
                .attr("width", barWidth - 5)
                .each(function(d){ 
                  if(d.year === "2014"){
                    d3.select(this)
                    .style('fill','#ea5454');
                  }else{
                    d3.select(this)
                    .style('fill','#4e97c4');
                  };
                });

        bars.transition()
          .duration(600)
          .ease(d3.easeLinear)
          .attr('y', function(d){ return yChart(d.purchase); })
          .attr('height', function(d){ return height - yChart(d.purchase); });

        chart.select('.y').call(yAxis);


        chart.select('.xAxis')
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis)
            .selectAll("text")
                .style("text-anchor", "end")
                .attr("dx", "-.8em")
                .attr("dy", ".15em")
                .attr("transform", function(d){
                    return "rotate(-65)";
                });

         }

    var margin = {top: 20, right: 20, bottom: 95, left: 50};
    var width = 400;
    var height = 500;

    var chart = d3.select(".chart")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var xChart = d3.scaleBand()
                .range([0, width]);

    var yChart = d3.scaleLinear()
                .range([height, 0]);

    var xAxis = d3.axisBottom(xChart);
    var yAxis = d3.axisLeft(yChart);


    chart.append("g")
        .attr("class", "y axis")
        .call(yAxis)

    chart.append("g")
        .attr("class", "xAxis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis)
        .selectAll("text")
        .style("text-anchor", "end")
        .attr("dx", "-.8em")
        .attr("dy", ".15em")
        .attr("transform", function(d){
            return "rotate(-65)";
                });

    chart.append("text")
        .attr("transform", "translate(-35," +  (height+margin.bottom)/2 + ") rotate(-90)")
        .text("Purchases");

    chart.append("text")
        .attr("transform", "translate(" + (width/2) + "," + (height + margin.bottom - 5) + ")")
        .text("Products");

    update(data2002);

You have the right idea...you want to achieve object constancy as described here by Mike Bostock. 您有正确的主意...您想要实现Mike Bostock 在此描述的对象恒定性。 The key for your constancy should be the "product" from your data (not "purchase"). 保持稳定性的关键应该是数据中的“产品”(而不是“购买”)。

In your update function, define bars like this: 在你update功能,定义bars是这样的:

var bars = chart.selectAll(".bar")
            .data(data, function(d){ return d.product; })

then separate the .enter , .exit and .transition functions: 然后分离.enter.exit.transition功能:

       bars.exit()
         .remove()
       bars.enter()
         ....
       bars.transition()

You have some strange stuff going on in your .enter function - like setting bar height to zero. .enter函数中发生了一些奇怪的事情,例如将条形高度设置为零。 So I modified your .enter and .transition functions like this: 因此,我修改了.enter和.transition函数,如下所示:

          bars.enter()
            .append("rect")
            .attr("class", "bar")
            .attr("x", function(d, i){return i * barWidth + 1 })
            .attr("y",function(d){ return yChart(d.purchase); })
            .attr("height",function(d){ return height - yChart(d.purchase); })
            .attr("width", barWidth - 5)
            .attr('fill', function(d){ 
              if(d.year === "2014"){
                return'#ea5454'
              }else{
                return'#4e97c4'
              }

            })
    bars.transition()
      .duration(600)
      .ease(d3.easeLinear)
      .attr('y', function(d){ return yChart(d.purchase); })
      .attr('height', function(d){ return height - yChart(d.purchase); })
      .style('fill', function(d){
        if(d.year === "2014"){
          return '#ea5454'
        } else {
          return '#4e97c4'
        }
      })

Here is a working jsfiddle: https://jsfiddle.net/genestd/asoLph2w/ 这是一个工作的jsfiddle: https ://jsfiddle.net/genestd/asoLph2w/
Note the buttons on top to achieve the transition. 注意顶部的按钮以实现过渡。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM