2015-10-16 115 views
2

我試圖保存數組中的圓的選擇,所以我可以稍後操作這些圓而不必搜索頁面上的所有圓。我希望能夠從超過一個,然後他們在創造了一個不同的功能訪問的社交圈。如何將d3選擇保存在數組中供以後使用D3.js?

// From outer function 
var selections = []; 

// From inner function A 
circles.on("click", function(da){ 
    d3.selectAll("circle").filter(function(db){ 
    var result = da.someProperty == db.someProperty; 
    var circle = d3.select(this); 
    if(result) selections.push(circle); 
    return result; 
    }) 
    .attr("fill", "red"); 
}); 

// From inner function B 
selections.forEach(function(circle){ 
    circle.attr("fill", "black");  // Doesn't work 
}); 

有沒有用我的選擇數組的內容屬性修改圈的方法嗎?

回答

2

在您的selections.forEach(...)中,看看「circle」實際上是什麼。從我測試過的(我必須提前創建變量「圈子」,這只是d3.selectAll('圈子'),但你應該真正包括你在提示中使用的東西),「循環「在你的函數B循環是指一個1單元格陣列持有另一個1單元格陣列,其中包含一個圓形引用(本地HTML/SVG圈,而不是D3包裝)。

變化在B環的功能來

d3.select(circle[0][0]).attr('fill','black'); 

內容或許有一個更優雅的,面向D3路,但這絕對有效,而且它仍然是簡單的。

編輯:經過進一步測試後,我不確定你爲什麼不能正常工作。一旦我將var circles = d3.selectAll('circle');添加到開頭,功能B循環就可以正常工作,假設您在運行之前實際單擊了一個圓圈。如果你沒有,你正在遍歷一個空的數組。

0

這裏的工作jsfiddle

var jsonCircles = [{ 
    "x_axis": 30, 
     "y_axis": 30, 
     "radius": 20, 
     "color": "green" 
}, { 
    "x_axis": 70, 
     "y_axis": 70, 
     "radius": 20, 
     "color": "purple" 
}, { 
    "x_axis": 110, 
     "y_axis": 100, 
     "radius": 20, 
     "color": "red" 
}, { 
    "x_axis": 150, 
     "y_axis": 230, 
     "radius": 70, 
     "color": "yellow" 
}, { 
    "x_axis": 300, 
     "y_axis": 100, 
     "radius": 90, 
     "color": "grey" 
}]; 

var svgContainer = d3.select("body").append("svg") 
    .attr("width", 400) 
    .attr("height", 400); 

var circles = svgContainer.selectAll("circle") 
    .data(jsonCircles) 
    .enter() 
    .append("circle"); 

var circleAttributes = circles.attr("cx", function (d) { 
    return d.x_axis; 
}) 
    .attr("cy", function (d) { 
    return d.y_axis; 
}) 
    .attr("r", function (d) { 
    return d.radius; 
}) 
    .style("fill", function (d) { 
    return d.color; 
}); 

var selection = []; 

d3.selectAll('circle')[0].forEach(function (circle) { 
    if (circle.r.baseVal.value > 20) { 
     selection.push(circle); 
    } 
}); 

alert('We have ' + selection.length + 'circle(s) selected'); 
selection.forEach(function (circle) { 
    circle.style.fill = "blue"; 
}); 
5

從D3的觀點有你的方法適用的一些改進,這將使你的代碼更具可讀性和D3ish。嘗試通過D3的concept of selections來獲得對其的理解。即使不知道你的整個代碼,張貼在你的問題的片段可能會被重構爲這樣的事:

// From outer function 
// This will hold the selection in the outer scope. 
var selections; 

// From inner function A 
circles.on("click", function(da){ 
    // Fill in the reference to the selection which is returned by filter(). 
    selections = d3.selectAll("circle").filter(function(db){ 
    return da.someProperty == db.someProperty; 
    }) 
    .attr("fill", "red"); 
}); 

// From inner function B 
// No need for an explicit loop here; D3 will take care of that. 
selections.attr("fill", "black"); 

filter()函數將返回你是經過選擇而無需擺弄任何輔助陣列。您只需在selections中存儲對此選擇的引用,並將其保存在外部範圍內。

當你稍後想要按照這個選擇進行操作時,不需要對數組進行顯式循環,因爲D3會處理這個問題。您可以調用其方法來處理屬性,樣式,事件處理程序等。有關所有方法的信息,請參見API docs,該方法可在d3.select()上獲得。