score:5

The problem with simply calling FeedDataToChart again is that it creates entirely new svg and path elements rather than reusing the existing ones. The inner redraw method you're using follows the standard D3 update pattern, so take that as an example for how to rework the update.

Start by separating initialization from drawing. There's no reason the scale and line generators need to change on every update, so get that out of the way early. Also create the svg element as soon as you can and don't change it unless you really need to. Likewise with the path element.

The general structure of any D3 visualization will consist of three distinct phases:

intialization - perform as soon as possible after script load

  • create scale and svg generator functions (scale, axis, line, area etc.)
  • create data cleanup & aggregation functions (nest, custom filters etc.)

creation - perform as soon as possible after DOM ready

  • create svg element (only ever call .append("svg") once per chart)
  • create chart and axis groups (see the margin conventions)

draw - perform when data is available

  • first segment by enter/update/remove selections
    • find existing data elements (.selectAll() on data element CSS class)
    • rebind data to chart
  • perform on enter selection
    • create chart data elements (only call .append(el) after .enter())
    • set chart data element CSS class (make this the canonical handle)
    • set static properties (but if you can put these in CSS all the better)
  • perform on enter and update selections
    • set dynamic properties (here is the call to .attr("d", line))
  • you may also have a remove portion (for exit selections)

For more information take a look at Mike Bostock's tutorial on selections in D3.

The create, update, remove process is actually pretty simple once you get used to it. Here's a prototypical example:

// select existing data elements and rebind data
var dots = d3.selectAll(".dot")
    .data(data);

// append a circle for new dots
dots.enter().append("circle")
    .attr("class", "dot")
    .attr("r", 4);

// remove old dots
dots.exit().remove();

// update all new and existing dots
dots.attr("cx", x)
    .attr("cy", y);

The key to writing simple and performant D3 is to minimize the changes you're making to the DOM, since DOM manipulation tends to be the major performance bottleneck.


Related Query

More Query from same tag