I want to simulate the situation where there is continuous incoming real time (dynamic) data and feed to the chart
Therefore, I try to demonstrate an animated line chart using d3 while the data array is required to be continuous updated every 1 second.
The original work is inspired by benjchristensen
And here is my modified html source: my source code
I try to populate the buffer[100]
with random number for every 1 second
by calling function startGenerator()
function startGenerator()
{
//signalGenerator();
setInterval("signalGenerator()", 1000); //
}
function signalGenerator()
{
var buffer = new Array(100);
var i;
for (i = 0; i < buffer.length; i++)
{
buffer[i] = Math.random() * 10;
}
FeedDataToChart("#graph1", 300, 300, "basis", true, 100, 100, buffer, 0);
}
Below is the FeedDataToChart()
parameter names:
function FeedDataToChart(id, width, height, interpolation, animate, updateDelay, transitionDelay, data, startIndex)
I use a counter
to check for the re-draw data index, every time when re-draw new data, counter
increase by 1
. Until the the counter < data.length-1
, the re-draw timer
should stop and get new data from the buffer[100]
again.
function stopTimer()
{
clearInterval(myTimer);
alert("The redraw timer stop here, get new data from buffer");
}
function startTimer()
{
if (myTimer == null)
{
myTimer = setInterval(function() {
if (counter < data.length - 1)
{
var v = data.shift(); // remove the first element of the array
data.push(v); // add a new element to the array (we're just taking the number we just shifted off the front and appending to the end)
if(animate)
{
redrawWithAnimation();
}
else
{
redrawWithoutAnimation();
}
counter++;
}
else
{
alert("no more data in buffer");
stopTimer();
counter = startIndex;
}
}, updateDelay);
}
}
My problem occurs when I tried to repeat the startGenerator()
function, the results shows like this:
I am pretty new to javascript. Can anyone pin point me how to pull data from the buffer
every 1 second
and update the single line chart continuously?
Thank you!
EDIT I update the source and problem has been minimized: My New Source
I add the .remove()
line at the stopTimer()
to remove the sgv-holded data and reset the global buffer to null
and call the startGenerator()
function again to pull new data when timer stop.
Now the only problem I having is that everytime when new graph is created, it create a new sgv path where below the previous one. The new graph is moving downwards everytime when it was created. Check the new source I updated today. You will catch my description after you run the code.
How can I fixed the sgv path at the same location everytime when I update it?
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
scale
, axis
, line
, area
etc.)nest
, custom filters etc.)creation - perform as soon as possible after DOM ready
.append("svg")
once per chart)draw - perform when data is available
.selectAll()
on data element CSS class)enter
selection
.append(el)
after .enter()
)enter
and update
selections
.attr("d", line)
)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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With