2013-02-13 68 views
2

我已經實現這個D3可視化http://bl.ocks.org/4745936,用來裝載的動態數據,而不是在我的情況下的.tsv格式d3.js動態數據重加載可能與退出()。除去()

,一旦我的服務器通過向選擇器提供新信息,第二個圖表將在第一個圖表下呈現,而不是修改現有圖形的內容。

我相信它與這個append方法有關。

var svg = d3.select(selector).append("svg") 
    .attr("width", width + margin.left + margin.right) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

,所以我嘗試之後,他們append('g');但我的JavaScript控制檯說,exit()方法不會在這一點上存在添加其他exit().remove()方法傳說和城市變量。

我覺得我有完全錯誤的方法,如何更新現有的圖形?讓第二個和第三個圖形與前一個圖形一起生成並不是我想要的結果

回答

1

我能因爲我的D3圖增加了一個SVG元素添加到現有選擇(對我來說一個div)與一些jQuery和CSS巫術

基本上解決了這個問題,我能來檢查名稱這是動態的

var svgtest = d3.select(selector+" > svg");獲取該div的svg子元素。那麼我可以使用jquery從dom中完全刪除該元素,然後讓d3繼續運行並追加svg的所有想要的東西!

var svgtest = d3.select(selector+" > svg"); 
    if(!svgtest.empty()) 
    { 
     $(selector+" > svg").remove(); 
    } 
2

你是對的append方法是每次都添加一個新的svg元素。爲了防止重複的圖表,你需要檢查svg元素是否已經存在。因此,嘗試這樣的事情在開始時:

var svg = d3.select("#mycontainer > svg") 
if (svg.empty()) 
    svg = d3.select(selector).append("svg"); 
... 

正如exit() docs指出,此方法僅由數據運算返回的選擇定義。所以請確保您在從.data(..)返回的選擇中調用退出。

+0

所以它正確地檢查選擇,但我仍然有退出的問題( ) 方法。 var legend = svg.selectAll('g') \t .data(cities) \t .enter(); \t \t legend.exit()。remove();這仍然「返回方法沒有退出」在我的控制檯 – CQM 2013-02-13 21:29:46

+0

這是我的代碼http://jsfiddle.net/ericps/8Axn7/ – CQM 2013-02-13 23:44:19

+0

@CQM如果你可以簡化你的代碼,並顯示錯誤,我認爲這將有助於兩個我們。例如,那裏的大部分內容(複雜數據,圖例,文本等)與問題無關。簡化這個問題,如果你沒有發現問題分享小提琴,我會看看。我上面提到的關於退出的文檔也是一個很好的資源。他們展示了一些可能有用的簡單例子。 – 2013-02-14 02:22:35

1

斯科特的答案是確保初始化只發生一次的一種方法。

不過,我更喜歡處理這個更D3-IC方式:

var svg = d3.select(selector) 
      .selectAll('svg') 
      .data([ dataFromTSV ]); // 1 element array -> 1 svg element 

// This will be empty if the `svg` element already exists. 
var gEnter = svg.enter() 
       .append('svg') 
       .append('g'); 

gEnter.append(...); // Other elements to be appended only once like axis 

svg.attr('width', ...) 
    .attr('height', ...); 

// Finally, working with the elements which are surely in the DOM. 
var g = svg.select("g") 
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

g.selectAll(...).attr(...); 

這種方法在the reusable charts examplesource code例證。

我喜歡這種方法,因爲它通過隱藏掉初始化和更新的邏輯使得代碼很聲明和真正的可視化。


我想修改原始例如:http://jsfiddle.net/8Axn7/5/http://jsfiddle.net/3Ztt8/

無論是圖例和圖表是從svgElem與數據的一個單一的元素定義爲:

var svgElem = d3.select("#multiLinegraph").selectAll('svg') 
      .data([cities]); 

// ... 

var svg = svgElem.select('g'); 

// ... 


var city = svg.selectAll(".city") 
    .data(
     function (d) { return d; }, 
     function (d) { return d.name; } // Object consistency 
    ); 

// ... 


var legend = svg.selectAll('g.legend') 
    .data(
     function(d) { return d; }, 
     function (d) { return d.name; } // Object consistency 
    ); 

此外,靜態屬性僅在元素輸入(或退出)時設置一次,而更新屬性在每次更新時設置(轉換):

gEnter.append("g") 
    .attr("class", "y multiLineaxis") 
    .append('text') 
    .attr("transform", "rotate(-90)") 
    .attr("y", 6) 
    .attr("dy", ".71em") 
    .style("text-anchor", "end") 
    .text("Requests (#)"); 

svg.select('g.y.multiLineaxis').transition().call(yAxis); 

在我看來,代碼完全遵循enter-update-exit循環。

+0

你能告訴我我使用的圖表是如何在jsfiddle中重寫以適應這種範式嗎? – CQM 2013-02-13 22:26:49

+0

@musically_ut我喜歡那種1元素數組的方法。不錯。 – 2013-02-13 23:12:39

+0

http://jsfiddle.net/ericps/8Axn7/這個版本不會在jsFiddle中渲染,但可以在這裏整理 – CQM 2013-02-13 23:43:46

1

你應該刪除舊的SVG,經過那麼你可以添加更新的排行榜第一。 爲此,您應該在添加svg之前添加一行。 和它的工作。

var flag=d3.select("selector svg").remove(); 

// ----你的舊代碼將在這裏開始-------

var svg = d3.select(selector).append("svg")