私はグラフをライブ更新しているのを見ることができるように、私は更新パターンに取り入れたいエリアチャートを持っています。私は棒グラフでこれを行うことができましたが、エリアチャートは最終的にデータポイントの量に適しています。エリアチャートを更新する
私の最善の試みは以下の通りです。更新プロセスは、2つの行選択と2つの領域選択の4つの部分に分割されています。これは私にとってうんざりしているようですが、それが私が働くように見えるようにする唯一の方法です。問題は、データを追加すると、グラフがブラウザで非常に低速で実行されてしまうことです。これは私に間違っていることを示唆しています。また、要素の不透明度は以前の静的グラフとは異なって表示され、新しいデータが追加される前に表示されるグラフの部分は、新しいデータを追加すると小さなスパイクに縮小されます。
日付でソートされたエリアチャートに更新パターンを組み込む正しい方法は何ですか?
//////////////////////////////////////////////////
// initial data
//////////////////////////////////////////////////
var tdata = [
{
"property":"humidity",
"date":"2016-06-28 05:47:10",
"value": 40, "unit": "\%"
},
{
"property":"humidity",
"date":"2016-06-28 05:47:20",
"value": 35, "unit": "\%"
},
{
"property":"humidity",
"date":"2016-06-28 05:47:30",
"value": 36, "unit": "\%"
} ,
{
"property":"humidity",
"date":"2016-06-28 05:47:40",
"value": 40, "unit": "\%"
},
{
"property":"temperature",
"date":"2016-06-28 05:47:15",
"value": 75, "unit": "F"
} ,
{
"property":"temperature",
"date":"2016-06-28 05:47:25",
"value": 70, "unit": "F"
} ,
{
"property":"temperature",
"date":"2016-06-28 05:47:35",
"value": 72, "unit": "F"
},
{
"property":"temperature",
"date":"2016-06-28 05:47:45",
"value": 75, "unit": "F"
} ,
];
/////////////////////////////////////////////////////////
// d3 code:
/////////////////////////////////////////////////////////
var canvas = d3.select('#disp')
.append('svg')
.attr('width', 1200)
.attr('height', 200);
var x = d3.scale.linear().range([0,700]);
var y = d3.scale.linear()
.domain([0, 100])
.range([200, 0]);
var line = d3.svg.line()
// .interpolate("cardinal")
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.value);
});
var area = d3.svg.area()
//.interpolate("cardinal")
.x(line.x())
.y1(line.y())
.y0(y(0));
var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse;
var lines = canvas.selectAll('path');
//////////////////// update function:
function update(dataset){
// parse new date strings
dataset.forEach(function(d) {
if(typeof(d.date) === "string"){ d.date = parseDate(d.date); }
});
// sort by date
dataset = dataset.sort(sortByDateAscending);
// update domain
x.domain(d3.extent(dataset, function (d) { return d.date; }));
// (1) make temperature line selection, update
lines = canvas.selectAll('.tline').data(dataset);
lines
.attr('class', 'tline')
.attr("d", function(d) {
return line(dataset.filter(function(d){ return d.property == 'temperature'}));
})
.style("stroke", function(d){ return 'black'; });
// append new data to selection
lines
.enter().append("path")
.attr('class', 'tline')
.attr("d", function(d) {
return line(dataset.filter(function(d){ return d.property == 'temperature'}));
})
.style("stroke", function(d) {
return 'black';
});
// remove
lines.exit().remove();
// (2) make temperature area selection, update
lines = canvas.selectAll('.tarea').data(dataset);
lines
.attr("class", "tarea")
.style('fill', 'red')
.style('opacity', '0.3')
.attr("d", function(d) {
return area(dataset.filter(function(d){ return d.property == 'temperature'}));
});
// append new data to selection
lines
.enter().append("path")
.attr("class", "tarea")
.style('fill', 'red')
.style('opacity', '0.3')
.attr("d", function(d) {
return area(dataset.filter(function(d){ return d.property == 'temperature'}));
});
//remove
lines.exit().remove();
// (3) make humidity line selection, update
lines = canvas.selectAll('.hline').data(dataset);
lines
.attr('class', 'hline')
.attr("d", function(d) {
return line(dataset.filter(function(d){ return d.property == 'humidity'}));
})
.style("stroke", function(d){ return 'black'; });
// append new data to selection
lines
.enter().append("path")
.attr('class', 'hline')
.attr("d", function(d) {
return line(dataset.filter(function(d){ return d.property == 'humidity'}));
})
.style("stroke", function(d) {
return 'black';
});
// remove
lines.exit().remove();
// (4) make humidity area selection, update
lines = canvas.selectAll('.harea').data(dataset);
lines
.attr("class", "harea")
.style('fill', 'steelblue')
.style('opacity', '0.3')
.attr("d", function(d) {
return area(dataset.filter(function(d){ return d.property == 'humidity'}));
});
// append new data to selection
lines
.enter().append("path")
.attr("class", "harea")
.style('fill', 'steelblue')
.style('opacity', '0.3')
.attr("d", function(d) {
return area(dataset.filter(function(d){ return d.property == 'humidity'}));
});
// remove
lines.exit().remove();
}
function sortByDateAscending(a, b) {
return Date.parse(a.date) - Date.parse(b.date);
};
//////////////////////////////////////////////////////////////
// main code:
//////////////////////////////////////////////////////////////
addObjs(tdata)
addObjs(tdata)
addObjs(tdata)
addObjs(tdata)
addObjs(tdata)
addObjs(tdata)
addObjs(tdata)
addObjs(tdata)
addObjs(tdata)
update(tdata);
function btnfunc(){
addObjs(tdata)
update(tdata);
}
// function to add new objects to dataset incremented by date
function addObjs(arr) {
var z = 1;
var h = JSON.parse(JSON.stringify(arr[arr.length-2]));
var t = JSON.parse(JSON.stringify(arr[arr.length-1]));
h.property = 'humidity'; h.unit = '\%';
t.property = 'temperature'; t.unit = 'F';
var time = dparse(t.date);
time+= z;
h.date = timeString(time.toString());
h.value = 15 + Math.floor(Math.random()*31);
time+= z;
t.date = timeString(time.toString());
t.value = 65 + Math.floor(Math.random()*28);
arr.push(h);
arr.push(t);
function timeString(ins) {
return ins.slice(0,4) + '-' + ins.slice(4,6) + '-' + ins.slice(6,8) + ' '
+ ins.slice(8,10) + ':' + ins.slice(10,12) + ':' + ins.slice(12);
}
function dparse(date){
var d = date.substr(0,10).replace(/-/g , '');
var t = date.substr(11,18).replace(/:/g , '');
var i = parseInt(d+t);
return i;
}
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.area {
fill: steelblue;
}
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
shape-rendering: crispEdges;
}
.tline {
fill: none;
stroke-width: 1px;
}
.hline {
fill: none;
stroke-width: 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="disp"></div>
<button onclick="btnfunc()">add</button>
DOMがたくさんあるので、それが遅くなりますレンダリングし、各更新はページ全体を再レンダリングします。設定した数の更新後に新しいd3レンダリングを作成するのはどうですか? –