javascript - D3 Multi-series transition overlapping data -
i have graph correctly plots several lines based on sensor's serial number. problem need transition new dataset , data overlap. here's have far......
var thresholdtemp = 72; var minutes = 5; var transinterval; //main function create graph plot function plot(date1, date2, interval) { var data; //if define date search parameter don't want have load interactive if (date1 == undefined && date2==undefined) { data = loadminutesjson(minutes); } else { data = searchjson(date1, date2, interval); } var margin = {top: 20, right: 80, bottom: 60, left: 50}, width = 960 - margin.left - margin.right , height = 500 - margin.top - margin.bottom; //re-order data more usable rest of script var parsedate = d3.time.format("%y-%m-%d %h:%m:%s").parse; //set x domain exist within date , times given var x = d3.time.scale().domain([getmindate(data), getmaxdate(data)]).range([0, (width)]); //y axis scale set start @ 45 degrees , go 30 degrees on highest temp var y = d3.scale.linear() .domain([ 45, getmaxtemp(data) + 10 ]) .range([height, 0]); //set line colors based on serial number, generates color based on ordinal value var color = d3.scale.category20().domain(d3.keys(data).filter(function(key) { return key;})); //.domain(d3.keys(data[0]).filter(function(key) { return key === 'serial';})); //define x axis var xaxis = d3.svg.axis() .scale(x) .orient("bottom") .tickformat(d3.time.format("%b %d %h:%m:%s")); //define y axis var yaxis = d3.svg.axis() .scale(y) .orient("left"); //when called creates line given datapoints var line = d3.svg.line() .interpolate("basis") .x(function(d) { return x(d.date);}) .y(function(d) { return y(d.reading); }); //an line define maximum temperature threshold var threshold = d3.svg.line() .x(function(d) { return x(d.date);}) .y(function(d) { return y(thresholdtemp); }); //append svg html element var svg = d3.select("#plot").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 + ")"); //define clipping boundaries svg.append("defs").append("clippath") .attr("id", "clip") .append("rect") .attr("width", (width + margin.left + margin.right)) .attr("height", height + margin.top + margin.bottom); //add x axis svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xaxis) .selectall("text") .style("text-anchor", "end") .attr("dx", "-.8em") .attr("dy", ".15em") .attr("transform" , function (d) {return "rotate(-35)"}); //add y axis , label denoting temperature in f 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("temperature (f)"); //create lines based on serial number var serial = svg.selectall(".serial") .data(data); var serials = serial.enter().append("g") .attr("class", "serial"); //add line threshold , align current time var threshelement = svg.selectall(".thresh") .data(data) .enter().append("g") .attr("class", ".thresh"); //add path draw lines , clipping stay within bounds var path = serial.append("path") .attr("clip-path", "url(#clip)") .attr("class", "line") .attr("d", function (d) {return line(d.values);}) .style("stroke", function(d,i) {return color(i);}); //custom path add line showing temperature threshold var threshpath = threshelement.append("path") .attr("clip-path", "url(#clip)") .attr("class", "line") .attr("d", function(d) { return threshold(d.values);}) .style("stroke", "red"); //add label end of threshold line denoting threshold threshelement.append("text") .attr("transform", "translate(" + x(getmaxdate(data)) + "," + y(thresholdtemp) + ")") .attr("x", 3) .attr("dy", ".35em") .text("threshold"); serial.exit().remove(); //add legend //plotlegend(data); //load in new data , add svg function transition() { data = loadminutesjson(minutes); x.domain([getmindate(data), getmaxdate(data)]); y.domain([45, getmaxtemp(data) + 10]); d3.select(".x.axis") .transition() .duration(500).call(xaxis) .selectall("text") .style("text-anchor", "end") .attr("dx", "-.8em") .attr("dy", ".15em") .attr("transform" , function (d) {return "rotate(-35)"}); d3.select(".y.axis").transition().duration(500).call(yaxis); serial.data(data).enter().append("g").attr("class", "serial"); d3.selectall("path") .attr("class", "line") .attr("d", function(d) { return line(d.values);}) .style("stroke", function(d,i) { return color(i);}); } if(date1 == undefined && date2 == undefined) { //set transition loop run every 30 seconds transinterval = setinterval(transition,30000); } } //set new time in minutes , re-draw graph function setminutes(newminutes) { if (transinterval) { clearinterval(transinterval); } d3.selectall("svg").remove(); console.log("setting new minutes " + newminutes); minutes=newminutes; plot(); } //search database data between 2 dates , create new plot of function searchdb(date1, date2, intervalinminutes) { if (transinterval) { clearinterval(transinterval); } d3.selectall("svg").remove(); plot(date1, date2, intervalinminutes); console.log("processing search "); } //quick function determine maximum date in dataset function getmaxdate(data) { var arr = []; (x in data) { arr.push(d3.max(data[x].values, function(d) { return d.date;})); } return d3.max(arr); //return d3.max(data[0].values, function(d) { return d.date;}); } //calculate minimum data function getmindate(data) { var arr = []; (x in data) { arr.push(d3.min(data[x].values, function(d) { return d.date;})); } return d3.min(arr); //return d3.min(data[0].values, function(d) { return d.date;}); } //calculate upper maximum temperature function getmaxtemp(data) { var arr = []; (x in data) { arr.push(d3.max(data[x].values, function(d) { return d.reading;})); } return d3.max(arr); //return d3.max(data, function(d) { return d3.max(data.values, function(d) {return d.reading})}); }
here's examples of data:
first
[{"serial":"2d0008017075f210","values":[{"date":"2013-08-23t20:43:46.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:44:16.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:44:46.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:45:16.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:45:47.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:46:17.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:46:47.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:47:17.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:47:47.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:48:17.000z","reading":76.1,"elevation":null,"room":null,"system":null}]},{"serial":"1d00080170496d10","values":[{"date":"2013-08-23t20:43:46.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:44:16.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:44:46.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:45:16.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:45:47.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:46:17.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:46:47.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:47:17.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:47:47.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:48:17.000z","reading":73.4,"elevation":null,"room":null,"system":null}]},{"serial":"380008017037ed10","values":[{"date":"2013-08-23t20:43:46.000z","reading":74.3,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:44:16.000z","reading":75.2,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:44:46.000z","reading":74.3,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:45:16.000z","reading":74.3,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:45:47.000z","reading":74.3,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:46:17.000z","reading":74.3,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:46:47.000z","reading":75.2,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:47:17.000z","reading":74.3,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:47:47.000z","reading":74.3,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:48:17.000z","reading":74.3,"elevation":null,"room":null,"system":null}]}]
and transitioning to:
[{"serial":"2d0008017075f210","values":[{"date":"2013-08-23t20:44:46.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:45:16.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:45:47.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:46:17.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:46:47.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:47:17.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:47:47.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:48:17.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:48:47.000z","reading":76.1,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:49:17.000z","reading":76.1,"elevation":null,"room":null,"system":null}]},{"serial":"1d00080170496d10","values":[{"date":"2013-08-23t20:44:46.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:45:16.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:45:47.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:46:17.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:46:47.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:47:17.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:47:47.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:48:17.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:48:47.000z","reading":73.4,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:49:17.000z","reading":73.4,"elevation":null,"room":null,"system":null}]},{"serial":"380008017037ed10","values":[{"date":"2013-08-23t20:44:46.000z","reading":74.3,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:45:16.000z","reading":74.3,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:45:47.000z","reading":74.3,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:46:17.000z","reading":74.3,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:46:47.000z","reading":75.2,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:47:17.000z","reading":74.3,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:47:47.000z","reading":74.3,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:48:17.000z","reading":74.3,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:48:47.000z","reading":74.3,"elevation":null,"room":null,"system":null},{"date":"2013-08-23t20:49:17.000z","reading":74.3,"elevation":null,"room":null,"system":null}]}]
update: i've modified code quite bit, jsfiddle here http://jsfiddle.net/8cguf/1/ i'm not sure why fiddle doesn't work, tested on webserver , works fine. i'm trying construct graph data1 variable in there , transition data2 variable.
Comments
Post a Comment