D3.js dynamically switching using live data
Long time lurker, learning D3 with enthusiasm! Anywhoo, I am working on Mr. Bostock's examples.
Now I have a fiddle that works just fine - it's smooth, refreshes fast, scales the x-axis and y-axis pretty well.
This is the timing diagram that I am trying to solve. Basically, I take sensor chains that come in a JSON array. My goal is to get this data in real time; The sensor sends the tempo, and I get a smooth reflection of this data on the graph in near real time. Here rub. Once I add the code to collect the JSON, things go from smooth as butter to choppy and crazy. This is what I'm working with ... Please understand that I am very new to D3.
Here is some nicely randomized code that displays the graph the way I want:
var n = 40,
duration = 750,
now = new Date(Date.now() - duration),
random = d3.random.normal(0, 0.2),
count = 0,
data = d3.range(n).map(random);
var margin = {
top: 20,
right: 20,
bottom: 20,
left: 40
},
width = 500 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var x = d3.time.scale()
.domain([now - (n - 2) * duration, now - duration])
.range([0, width]);
var y = d3.scale.linear()
.domain([0, d3.max(data)])
.range([height, 0]);
var line = d3.svg.line()
.interpolate("basis")
.x(function (d, i) {
return x(now - (n - 1 - i) * duration);
})
.y(function (d, i) {
return y(d);
});
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 + ")");
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var axis = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(x.axis = d3.svg.axis().scale(x).orient("bottom"));
var yAx = svg.append("g")
.attr("class", "y axis")
.call(y.axis = d3.svg.axis().scale(y).orient("left"));
var path = svg.append("g")
.attr("clip-path", "url(#clip)")
.append("path")
.datum(data)
.attr("class", "line");
var transition = d3.select({}).transition()
.duration(750)
.ease("linear");
tick();
function tick() {
transition = transition.each(function () {
// update the domains
now = new Date();
x.domain([now - (n - 2) * duration, now - duration]);
y.domain([0, d3.max(data) + 10]);
// push a new data point onto the back
data.push(20 + Math.random() * 100);
// redraw the line, and slide it to the left
path.attr("d", line)
.attr("transform", null);
// slide the x-axis left, rescale the y-axis
axis.call(x.axis);
yAx.call(y.axis);
// slide the line left
path.transition()
.attr("transform", "translate(" + x(now - (n - 1) * duration) + ")");
// pop the old data point off the front
data.shift();
}).transition().each("start", tick);
}
svg {
font: 10px sans-serif;
}
.line {
fill: none;
stroke: orange;
stroke-width: 1.5px;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Now I understand that my poor understanding of transitions is probably keeping me stuck. I need help with this! My problem starts when I add the following:
First, I add var JSONdata = [];
as global and then immediately after I function tick() {
transition = transition.each(function () {
add the JSON code:
d3.json("tempdata.php", function(error, data){
JSONdata = data;
data.forEach(function(d) {
JSONdata.temp = +d.temp;
})
I conclude by ending the end of the entire tick block with a final })
This is how it works ... but it's slow and choppy! There seem to be dragons in my crossings ...? I would like to have as much realtime time as possible, but even up to 5 seconds since buffered latency would be acceptable. Can anyone reach out a hand or some kind of enlightenment?
I would like the graph to display a constant line with the last updated value, so even if the gauge is disabled, I will see the last value. Ultimately, of course, I need to develop a circular approach to the type of database and actually solve the problem of better handling the timestamp. But it could be the next day.
My JSFiddle with only randomized data: http://jsfiddle.net/6z9qe46e/7/
source to share
No one has answered this question yet
Check out similar questions: