1

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

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)”(没关系,根据这篇文章

我下面的代码有效,但我怀疑它不是对性能最友好的。例如,频率“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>
4

1 回答 1

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 的东西

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

于 2012-11-19T00:32:09.887 回答