如何在不重绘已存在的数据点的情况下更新此数据?

时间:2012-11-19 00:07:45

标签: javascript svg d3.js

D3新手。我正在尝试修改显示here的简单条形图示例。我正在尝试更新数据但缺少一些基本的东西。我正在努力跟随here,迈克谈论对象的持久性。具体来说,我试图在我的代码中实现以下目标:

Key functions can be useful for improving performance independent of transitions. For example, if you filter a large table, you can use a key function to reduce the number of DOM modifications: reorder DOM elements in the update selection rather than regenerating them. We used this technique at Square to improve the performance of merchant analytics, and it’s one of the reasons that D3 is faster than most template frameworks.

(在我的情况下,我的关键功能只是“.data(data)”(根据this post,这没关系)

我的代码可以使用,但我怀疑它不是最友好的。例如,频率“70”在两组数据中,但通过“移除”数据,我实际上是重绘它。 (如果我不首先“删除”数据,则绘制另一个图表,而不是刚刚获得更新数据的旧图表)。如何修改下面的代码以遵守关键功能,以便两个数据集中存在的数据不会重新绘制?

我的条形码代码:

<!DOCTYPE html>
<meta charset="utf-8">
<style>

body {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.bar {
  fill: steelblue;
}

.x.axis path {
  display: none;
}

</style>
<body>

<button id="change" name="change">Update</button>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js" type="text/javascript"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>


<script>
$(document).ready(function () { 
    var old_data = [{"letter": "A","frequency": "50"},
                {"letter": "B","frequency": "60"},
                {"letter": "C","frequency": "70"}, // this also appears in new_data
                {"letter": "D","frequency": "80"},
                ];


    draw_chart(old_data);

    $("#change").click(function(){

        var new_data = [{"letter": "A","frequency": "10"},
                        {"letter": "B","frequency": "20"},
                        {"letter": "C","frequency": "70"}, // this appears in old_data
                        {"letter": "D","frequency": "30"},
                        ];


        var bar = d3.select('body').selectAll('svg').remove();// delete this line and you'll get multiple charts rather than just updating the data in the original chart
        draw_chart(new_data);
    });
});

</script>


<script>
function draw_chart(data){

var margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], .1);

var y = d3.scale.linear()
    .range([height, 0]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

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

  data.forEach(function(d) {
    d.frequency = +d.frequency;
  });

  x.domain(data.map(function(d) { return d.letter; }));
  y.domain([0, d3.max(data, function(d) { return d.frequency; })]);

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Frequency");

  svg.selectAll(".bar")
      .data(data)
      .enter().append("rect")
      .attr("class", "bar")
      .attr("x", function(d) { return x(d.letter); })
      .attr("width", x.rangeBand())
      .attr("y", height)
      .attr("height","0")
      .transition()
      .delay(function(d, i) { return i*300 })
      .duration(1000) 
      .attr("y", function(d) { return y(d.frequency); })
      .attr("height", function(d) { return height - y(d.frequency); });
  }

</script>

1 个答案:

答案 0 :(得分:1)

首先,你有这条线的原因,

var bar d3.select('body')...remove() // delete this line and you'll get double...

请注意,draw_chart您的页面始终会附加到页面上。你需要改变这一行,

var svg = d3.select("body").append("svg")

到不会不断附加新svg的东西

如果我有更多时间,我会看看主要问题。