2015-07-20 155 views
0

我試圖修改每秒更新線圖的代碼。D3.js將變量傳遞到函數

該函數接受一個名爲path的變量,並使用它在屏幕上製作一個動畫,就像線圖正在移動一樣。

這是一段代碼片段。 (整個代碼,工作示例,並引用在此問題的最後聯繫。)

var path = svg.append("g") 
    .attr("clip-path", "url(#clip)") 
    .append("path") 
    .datum(data) 
    .attr("class", "line") 
    .attr("d", line); 

tick(); 

function tick() { 

    // push a new data point onto the back 
    data.push(random()); 

    // redraw the line, and slide it to the left 
    path 
     .attr("d", line) 
     .attr("transform", null) 
    .transition() 
     .duration(500) 
     .ease("linear") 
     .attr("transform", "translate(" + x(-1) + ",0)") 
     .each("end", tick); 

    // pop the old data point off the front 
    data.shift(); 

} 

我所試圖做的是改變了功能,因此,它需要的路徑變量作爲自變量,從而使我可以使用相同的功能(滴答)來修改各種不同的路徑。

但是,當我改變了上面的代碼是這樣的:

tick(path); 

    function tick(path) { /*same as before*/ } 

我得到的類型錯誤path.attr是不是一個函數。

而且,如果不是,我嘗試做這樣的事情:

tick(d3.select(path)); 

    function tick(path) { /*same as before*/ } 

我得到的錯誤:無法讀取的未定義的屬性「長度」。

有人可以幫我嗎?

工作實施例:向下滾動到第二曲線:http://bost.ocks.org/mike/path/

工作代碼:https://gist.githubusercontent.com/mbostock/1642874/raw/692ec5980f12f4b0cb38c43b41045fe2fe8e3b9e/index.html

引爲代碼,例如:mbostock在Github

回答

1

該錯誤不通過第一次調用tick(path)引起但在tick()被呼叫回叫時,後續呼叫由.each("end", tick);註冊。這些調用不會將所需參數path傳遞給您的函數。而且,從D3的源頭看,我沒有看到將此參數傳遞給回調的方法。

你可以通過你想讓它作用於路徑參數化的回調函數規避這些問題:

tick(path)(); 

function tick(path) { 
    var paramTick = function() { 
     // push a new data point onto the back 
     path.datum().push(random()); 

     // redraw the line, and slide it to the left 
     path 
      .attr("d", line) 
      .attr("transform", null) 
     .transition() 
      .duration(500) 
      .ease("linear") 
      .attr("transform", "translate(" + x(-1) + ",0)") 
      .each("end", paramTick); 

     // pop the old data point off the front 
     path.datum().shift(); 
    }; 
    return paramTick; 
} 

這其中使用了閉保存參考,爲未來的呼叫路徑。函數tick(path)定義了一個內部函數paramTick(),它基本上是您以前使用的函數。但是,它確實通過封閉來保存對參數path的引用。請注意,它將自身的引用作爲end事件的回調參數,而不是tick()。這樣你會得到一個回調結束了它獲取由呼叫

tick(path)(); 

調用參數化到tick(path)返回即將由第二組括號執行您呈現邏輯的參數化版本。

我設置了一個工作JSFiddle移動兩條路徑來證明這一點。


雖然這確實回答你的問題,但它似乎不是一個完美的解決方案。看看移動兩條路徑的例子,你會發現它們會偶爾稍微不同步。這是由於爲每條路徑使用不同的轉換而導致的,這些轉換不會完全同步。

在我看來,更好的方法是將多個路徑分組爲一個g並將轉換應用到該組。只需對原始代碼(JSFiddle v2)稍作修改即可實現所有路徑的平滑同步移動。

var data = [ 
     d3.range(n).map(random), 
     d3.range(n).map(random) 
]; 

var paths = group.selectAll("path") 
     .data(data) 
     .enter() 
      .append("path") 
      .attr("class", function(d,i) { 
       return "line" + i; 
      }) 
      .attr("d", line); 

tick(); 

function tick() { 
     // push a new data point onto the back 
    paths.each(function(d) {d.push(random());}); 

    // redraw the line 
    paths 
     .attr("d", line); 

    // Apply the transition to the group 
    group 
     .attr("transform", null) 
     .transition() 
     .duration(500) 
     .ease("linear") 
     .attr("transform", "translate(" + x(-1) + ",0)") 
     .each("end", tick); 

    // pop the old data point off the front 
    paths.each(function(d) {d.shift();}); 
} 
+0

感謝您關注此事並提供更好的解決方案! – codersun3