私は d3 を使用して、ユーザーがグラフの 1 つの範囲をドラッグすると両方ともズームできる 2 つの折れ線グラフを作成しています。ドラッグイベントの最後に各グラフを完全に再描画することで実装できましたが、更新を行い、アニメーション化されたトランジションを実行したいと思います。何らかの理由で、グラフは更新を開始しますが、新しいデータをプロットしないため、グラフが 1 つだけ更新されている場合でも、代わりに空のグラフになります。更新の試行の前後に console.log(newdata) を実行しましたが、配列には十分なデータがあり、元のデータと同じようにフォーマットされています。私は非常に多くのポイント (数千) を持っていますが、少なくとも折れ線グラフとして、このような大規模なデータセットをかなりうまく処理する d3 の例を見てきました。Firebug を使用すると、エラーは発生しません。関数が完了します (四角形が削除されます)。スケールも更新する必要があることはわかっていますが、少なくとも最初にデータを更新したいと思います。私は d3 にかなり慣れていないので、ばかげたことをしていても驚かないでしょう。どんな助けでも大歓迎です。
以下は線を描画するコードで、その後にドラッグ イベントを処理するコードが続きます。
var line = d3.svg.line()
.x(function(d){return x_scale(d.x)})
.y(function(d){return y_scale(d.y)})
d3.select("#graph" + pointnum + " svg g")
.append("path")
.attr("d", line(data))
.attr("class", "dist_line");
var dragrect;
var dragit = d3.behavior.drag()
.on("dragstart", function(){
omsi_globals.startx = Math.round(d3.mouse(this)[0]);
dragrect = d3.select("#graph" + pointnum + " svg g")
.append("rect")
.attr("x", omsi_globals.startx)
.attr("y", 0)
.attr("width", 1)
.attr("height", omsi_globals.chart_dimensions.height)
.attr("fill", "gray")
.attr("opacity", ".1");
})
.on("drag", function(){
var currx = d3.mouse(this)[0];
if(omsi_globals.startx > currx){
dragrect.transition()
.attr("x", currx)
.attr("width", Math.abs(currx - omsi_globals.startx))
.delay(0)
.duration(10);
}
else dragrect.transition()
.attr("width", Math.abs(currx - omsi_globals.startx))
.delay(0)
.duration(10);
})
.on("dragend", function(){
var startx = omsi_globals.startx;
var endx = Math.round(d3.mouse(this)[0]);
//make sure the drag covered more than one pixel. If not, fade out the rect
if(Math.abs(startx - endx)< 1){
dragrect.transition().attr("width", 0);
return;
}
//people can drag both directions, so figure out which is lower and which is higher
var lowerx = Math.min(startx, endx);
var higherx = Math.max(startx, endx);
//we'll scale as a proportion of the current x scale (not indices, which are more regular than the data)
var currxmin = omsi_globals.d3data[pointnum-1][0].x;
var currxmax = omsi_globals.d3data[pointnum-1][omsi_globals.d3data[pointnum-1].length-1].x;
var chartwidth = omsi_globals.chart_dimensions.width;
var newmin = ((lowerx/chartwidth) * (currxmax - currxmin)) + currxmin;
var newmax = ((higherx/chartwidth) * (currxmax - currxmin)) + currxmin;
//decide if it's time to switch to raw data or not
var sourcedata = [];
var newdata = [];
//switch to raw data if down to less than threshold width
if(newmax - newmin < omsi_globals.threshold) sourcedata = omsi_globals.plotpoints[pointnum-1].raw;
else sourcedata = omsi_globals.d3data[pointnum-1];
for(i=0; i<sourcedata.length; i++){
if(sourcedata[i].x < newmax && sourcedata[i].x > newmin){
newdata.push(sourcedata[i]);
}
}
//update the global variables to be read by d3
omsi_globals.d3data[pointnum-1] = newdata;
omsi_globals.d3xranges[pointnum-1] = [newdata[0].x, newdata[newdata.length-1].x];
d3.selectAll("#graph" + pointnum + " path")
.data(newdata)
.transition()
.duration(2500)
.attr("d", line);
dragrect.remove();
});