1

d3 を使用してビジュアライゼーションを作成しています。これには、上に 60 個、下に 60 個の長方形があります。各長方形には、約 100 ~ 150 個の円が含まれます。データは WebSocket 経由でストリーミングされます。フィルタリングを行わないと、更新に非常に時間がかかります。選択的な更新によって最適化しようとしています。ただし、.filter() を完全には理解していないようです。これは、長方形を扱うコードの部分への jsFiddle です。

http://jsfiddle.net/vjaT2/1/

関数 updateRect の js コメントからわかるように、いくつかのアプローチを試しました。1. .data 内のフィルタリング 2. ID を作成し、ID に対して selectAll を実行します。

しかし、どちらのアプローチも機能しません。

私が行方不明または間違っていることについて何か助けはありますか?

    var bottom_rects = 1;
var top_rects = 1;
var rects = [];

function generate_rect(){
    var created = '';

    // 6(*10) top rectangles & 6(*10) bottom rectangles 

    if(bottom_rects <= top_rects-1) {
        new_rect = {"name":"rect_bottom_"+bottom_rects,"location":"bottom","minx":0,"miny":Math.floor((2*h)/3),"maxx":0,"maxy":h};
        rects.push(new_rect);
        //fix x values
        var step  = Math.floor(w/bottom_rects);
        var x = 0;
        for (var i = 0; i < rects.length; i++) {
            var item = rects[i];
            if (item.location == "bottom"){
                    item.minx = x;
                    item.maxx = x+step;
                    x=x+step;
            }

        }
        bottom_rects++;
        created = "bottom";
    } else {
        new_rect = {"name":"rect_top_"+top_rects,"location":"top","minx":0,"miny":0,"maxx":0,"maxy":Math.floor(h/3)};
        rects.push(new_rect);
        //fix x values
        var step  = Math.floor(w/top_rects);
        var x = 0;
        for (var i = 0; i < rects.length; i++) {
            var item = rects[i];
            if (item.location == "top"){
                    item.minx = x;
                    item.maxx = x+step;
                    x=x+step;
            }
        }
        top_rects++;
        created = "top";
    }
    updateRect(created);
}

var w = 1200,
    h = 760;

var vis = d3.select("#chart").append("svg:svg")
    .attr("width", w)
    .attr("height", h);

function updateRect(location) {
    //var allrects = vis.selectAll("rect")
    var allrects = vis.selectAll(".rect_"+location)
        //.data(rects.filter(function(d)  { return d.location == location; }))
        .data(rects)
            //update
            .attr("x", function(d)      {  return d.minx;        })
            .attr("y", function(d)      {  return d.miny;        })
            .attr("width",function(d)   {  return d.maxx-d.minx; })
            .attr("height", function(d) {  return d.maxy-d.miny; })
            //create
        .enter().append("rect")         
            .attr("x", function(d)      {  return d.minx;        })
            .attr("y", function(d)      {  return d.miny;        })
            //.attr("id", "rect_"+location)
            .attr("width",function(d)   {  return d.maxx-d.minx; })
            .attr("height", function(d) {  return d.maxy-d.miny; })
            .attr("fill", "blue")
            .attr("stroke", "black")
            .style("stroke-width", 2)
            .style("fill-opacity", 0.2)
        .exit().remove();
}   

for(var i =0; i < 12; i++) setTimeout(generate_rect,(i+1)*200);
4

1 に答える 1

2

2 つの異なるfilter()機能があります。1 つ目は、任意の配列に適用できるJavascriptであり、D3 とは関係ありません。filter2 つ目は、選択に適用できるD3です。filter

選択的更新の場合、原則として両方を使用できます。.data()最初のケースでは、 (既に試したように) に渡す前にデータをフィルター処理し、既存の DOM 要素に一致するものを操作します。ここで重要なことは、ほぼ確実.data()に、配列内のデータを DOM 要素に一致させる方法を伝える関数を に提供する必要があるということです。詳細については、ドキュメントを参照してください。

あなたがしたいことのために、.filter()選択を操作する他の機能を使用することをお勧めします。つまり、通常の場合と同じように選択し、その選択から要素をフィルター処理します。あなたの例では、コードは次のようになります。

vis.selectAll("rect")
   .filter(function(d) { return d.location == location; });

または、クラスごとに選択する 3 番目の方法 (これも試しました) を使用できますが、他のフィルター関数は必要ありません。ただし、これらの要素に新しいデータをバインドする場合は、要素の特定のサブセット用のデータのみを渡すように注意する必要があります。つまり、データを に渡す前にフィルター処理する必要があります.data()。実際には、データをいくつかの場所に分割する必要があるため、これはおそらく最も直感的でない方法です。

于 2013-09-21T09:13:12.270 に答える