【问题标题】:How to transition between updated data of bar chart, in d3?如何在d3中的条形图更新数据之间转换?
【发布时间】:2017-06-25 01:41:08
【问题描述】:

我正在尝试使用 D3 了解条形图中的转换。我现在正在做的是更新两个不同数据集之间的图表。我有一个过渡,但它是从轴的底部开始的,而不是在两者之间过渡。我的目标是让它在两者之间过渡,然后改变颜色。我正在使用这个有用的example 来理解更新的数据(我的 sn-p 并没有太大的不同)。感谢您的观看。

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

【问题讨论】:

  • 你的问题不清楚。图表正在更新。你到底有什么问题?
  • @GerardoFurtado 很抱歉混淆了。我试图让酒吧在过渡中相互升起。现在,当单击按钮时,它们从图表底部上升。这个网站上的最终结果条形图有一个我正在寻找的转换示例。 davesquared.net/2014/09/d3-update-a-bar-chart.html

标签: javascript d3.js charts bar-chart


【解决方案1】:

您有正确的想法...您希望实现对象恒定性,正如 Mike Bostock 所描述的 here。保持不变的关键应该是数据中的“产品”(而不是“购买”)。

在您的update 函数中,像这样定义bars

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

然后将.enter.exit.transition函数分开:

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

.enter 函数中发生了一些奇怪的事情——比如将条形高度设置为零。所以我像这样修改了你的 .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'
        }
      })

这是一个有效的 jsfiddle:https://jsfiddle.net/genestd/asoLph2w/
请注意顶部的按钮以实现过渡。

【讨论】:

  • 嗯,好的。感谢您指出这一点并发送 Mike Bostock 关于恒常性的描述。我以前没见过。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-26
相关资源
最近更新 更多