I am using the dimple js library to draw a stacked area chart. I want to update the data based on user input.
I have a working example, that visually looks correct, however on each update, there are more elements being added to the svg, so that after a few updates of the chart the script visibly slows down.
Below is an example script illustrating the problem. It is adapted from an answer related to updating a dimple bar chart: Update dimple.js chart when select a new option
Example:
<div id="chartContainer"></div>
<button id="btn">Click Me</button>
<script type="text/javascript">
var svg = dimple.newSvg("#chartContainer", 590, 400);
var data = [
{ Animal: "Cats", Series: "1", Value: (Math.random() * 1000000) },
{ Animal: "Dogs", Series: "1", Value: (Math.random() * 1000000) },
{ Animal: "Mice", Series: "1", Value: (Math.random() * 1000000) },
{ Animal: "Cats", Series: "2", Value: (Math.random() * 1000000) },
{ Animal: "Dogs", Series: "2", Value: (Math.random() * 1000000) },
{ Animal: "Mice", Series: "2", Value: (Math.random() * 1000000) },
{ Animal: "Cats", Series: "3", Value: (Math.random() * 1000000) },
{ Animal: "Dogs", Series: "3", Value: (Math.random() * 1000000) },
{ Animal: "Mice", Series: "3", Value: (Math.random() * 1000000) }
];
var myChart = new dimple.chart(svg, data);
myChart.setBounds(60, 30, 510, 305)
var x = myChart.addCategoryAxis("x", "Animal");
x.addOrderRule(["Cats", "Dogs", "Mice"]);
myChart.addMeasureAxis("y", "Value");
myChart.addSeries("Series", dimple.plot.area);
myChart.draw();
d3.select("#btn").on("click", function() {
myChart.data = [
{ Animal: "Cats", Series: "1", Value: (Math.random() * 1000000) },
{ Animal: "Dogs", Series: "1", Value: (Math.random() * 1000000) },
{ Animal: "Mice", Series: "1", Value: (Math.random() * 1000000) },
{ Animal: "Cats", Series: "2", Value: (Math.random() * 1000000) },
{ Animal: "Dogs", Series: "2", Value: (Math.random() * 1000000) },
{ Animal: "Mice", Series: "2", Value: (Math.random() * 1000000) },
{ Animal: "Cats", Series: "3", Value: (Math.random() * 1000000) },
{ Animal: "Dogs", Series: "3", Value: (Math.random() * 1000000) },
{ Animal: "Mice", Series: "3", Value: (Math.random() * 1000000) }
];
myChart.draw(1000);
});
</script>
How can I update an area chart like this cleanly, such that any previous data is removed? (I could destroy the svg and redraw, but this would lose the animated effect)
Thanks
UPDATE:
I have found a partial solution. Each time the chart is updated, a series of non-visible markers are added at each data point, but are not removed. You can manually remove them using
d3.selectAll(".dimple-custom-line-marker").remove();
This is placed before .draw():
d3.select("#btn").on("click", function() {
myChart.data = [
{ Animal: "Cats", Series: "1", Value: (Math.random() * 1000000) },
{ Animal: "Dogs", Series: "1", Value: (Math.random() * 1000000) },
{ Animal: "Mice", Series: "1", Value: (Math.random() * 1000000) },
{ Animal: "Cats", Series: "2", Value: (Math.random() * 1000000) },
{ Animal: "Dogs", Series: "2", Value: (Math.random() * 1000000) },
{ Animal: "Mice", Series: "2", Value: (Math.random() * 1000000) },
{ Animal: "Cats", Series: "3", Value: (Math.random() * 1000000) },
{ Animal: "Dogs", Series: "3", Value: (Math.random() * 1000000) },
{ Animal: "Mice", Series: "3", Value: (Math.random() * 1000000) }
];
d3.selectAll(".dimple-custom-line-marker").remove();
myChart.draw(1000);
});
(NB: you might need ".dimple-marker" rather than ".dimple-custom-line-marker" if the area chart just has one series)
This works fine in Firefox, but sometimes in Chrome or safari the chart freezes. The error message in the console reads:
TypeError: Cannot read property 'key' of undefined
at SVGCircleElement.<anonymous> (https://www.../js/dimple.v2.3.0.min.js:2:16003)
....