2012-12-12 22 views
3

我試圖每隔5秒,通過改變lineData陣列我饋送到D3線函數之後,繪製一系列線:d3.js - 未捕獲的類型錯誤:對象沒有方法「退出」

以下是相關代碼摘錄如下:

var svg = d3.select("body").append("svg:svg") 
     .attr("width", width + margin.left + margin.right) 
     .attr("height", height + margin.top + margin.bottom) 
     .attr("id", "svgMain") 
     .append("g") 
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")") 
     .call(drag); 

var lines = svg.append("g") 
     .attr("id", "lines"); 

function changingLines() { 
     lines.selectAll("line") 
     .data(lineData) 
     .enter().append("line") 
     .attr("x1", function(d, i) { console.log(d[0][0]); return d[0][0];}) 
     .attr("y1", function(d, i) { console.log(d[0][1]); return d[0][1];}) 
     .attr("x2", function(d, i) { return d[1][0];}) 
     .attr("y2", function(d, i) { return d[1][1];}) 
     .style("stroke", "#000") 
     .style("stroke-width", "0.5") 
     .attr("class", "lines"); 

    lines.selectAll("line").exit().remove(); 
    setTimeout(changingLines, 2000); 
} 

我每隔2秒調用一次函數changingLines(),爲lineData數組指定不同的值。

我得到的錯誤:遺漏的類型錯誤:對象沒有方法「退出

我在做什麼錯?

回答

18

實際上,這段代碼有幾個相關的問題。當您致電changingLines時,將更新其屬性的唯一元素是enter選擇中的元素(呼叫.enter()返回enter選擇`)。

請記住,默認情況下,如果您傳遞給它的數組中有新元素,則默認情況下,.data()只會將元素添加到enter選擇中。

// Old data array: 
var data = [1, 2, 3, 4]; 

// New data array: 
var newData = [5, 6, 7, 8, 9]; 

/* 
The first 4 elements in newData will replace the first 4 elements of oldData. 
The number of new elements (which will be in the enter() selection) is only 1. 
*/ 

你應該做的是保存參加由您的通話data計算,並用它來單獨訪問enterexitupdate選擇。

var linesContainer = svg.append("g").attr("id", "lines"); 

function changingLines() { 

    /* Compute the data join */ 
    var lines = linesContainer.selectAll("line").data(lineData); 

    /* Enter */ 
    lines.enter().append("line"); 

    /* Exit */ 
    lines.exit().remove(); 

    /* Update */ 
    lines 
     .attr("x1", function(d, i) { console.log(d[0][0]); return d[0][0];}) 
     .attr("y1", function(d, i) { console.log(d[0][1]); return d[0][1];}) 
     .attr("x2", function(d, i) { return d[1][0];}) 
     .attr("y2", function(d, i) { return d[1][1];}) 
     .style("stroke", "#000") 
     .style("stroke-width", "0.5") 
     .attr("class", "lines"); 

    setTimeout(changingLines, 2000); 
} 

這將刪除舊line元素,並添加新的元素line它更新的屬性和樣式之前。

https://github.com/mbostock/d3/wiki/Selections#wiki-enter

The enter selection merges into the update selection when you append or insert. This approach reduces code duplication between enter and update. Rather than applying operators to both the enter and update selection separately, you can now apply them to the update selection after entering the nodes. In the rare case that you want to run operators only on the updating nodes, you can run them on the update selection before entering new nodes.

這也應該不能夠打電話exit()解決您的問題。當您第二次致電lines.selectAll("line")時,您正在創建一個新選區,因此您無法訪問在執行上一次聯接時計算的選區。

讀,重讀這篇文章:http://bost.ocks.org/mike/join/

+4

感謝,這真的幫助了! – shilpanb

相關問題