2015-04-18 56 views
3

如果你關注Mike Bostock的bl.ocks,你知道在過去的8個月裏,d3.geo.pipeline()一直是他項目的一個常用組件。什麼是d3.geo.pipeline?

但它是做什麼的?

你看他設置的管道像這樣:

var sketch = d3.geo.pipeline() 
     .source(d3.geo.jsonSource) 
     .pipe(resample, .020) 
     .pipe(jitter, .004) 
     .pipe(smooth, .005) 
     .sink(d3.geo.jsonSink); 

via

有一個在d3.geo wiki.

一些美化JS代碼示例中使用任何文檔中未發佈的D3揭示本功能:

lo.geo.pipeline = function() { 
     var n = []; 
     return { 
      source: function() { 
       return n[0] = arguments, this 
      }, 
      pipe: function() { 
       return n.push(arguments), this 
      }, 
      sink: function() { 
       for (var t, e = arguments[0].apply(null, [].slice.call(arguments, 1)), r = e; t = n.pop();) { 
        var u = [].slice.call(t, 1); 
        u.push(e), e = t[0].apply(null, u) 
       } 
       return function() { 
        return e.apply(this, arguments), r.value && r.value() 
       } 
      } 
     } 

它也出現在這些bl.ocks:

回答

2

我不熟悉d3.js,但我看着它源代碼,發現該功能位於分支graphics-pipeline

例如,你可以在這裏找到相關的代碼:https://github.com/mbostock/d3/commit/a3f2adab7f85e2a0c82288ead88c1e484c9e3ea3


一小段代碼來說明它是如何工作的:

var pipeline = function() { 
 
    var pipes = []; 
 
    return { 
 
     source: function() { 
 
      pipes[0] = arguments; 
 
      return this; 
 
     }, 
 
     pipe: function() { 
 
      pipes.push(arguments); 
 
      return this; 
 
     }, 
 
     sink: function() { 
 
      var sink = arguments[0].apply(null, [].slice.call(arguments, 1)), 
 
       pipe; 
 

 
      while (pipe = pipes.pop()) { 
 
       var args = [].slice.call(pipe, 1); 
 
       args.push(sink); 
 
       sink = pipe[0].apply(null, args); 
 
      } 
 

 
      return sink; 
 
     } 
 
    }; 
 
}; 
 

 
var log = document.getElementById('log'); 
 

 
function f() { 
 
    var argsAsString = Array.prototype.join.call(arguments, ', '); 
 
    var resultName = 'r' + f.callCounter++; 
 

 
    log.innerHTML += resultName + ' = f(' + argsAsString + ')<br>'; 
 

 
    return resultName; 
 
} 
 

 
f.callCounter = 1; 
 

 
pipeline(). 
 
    source(f, 'a', 1). 
 
    pipe(f, 'b', 2). 
 
    pipe(f, 'c', 3). 
 
    sink(f, 'd', 4);
<div id="log"></div>

有關該功能的幾點意見:

  1. 方法sourcepipe使用相同的私有財產pipes。區別僅在於設置爲pipespipes[0])的初始值,每次調用pipe時都會將新管道推入集合。
  2. 先前的事實爲我們提供了關於d3.geo.jsonSource內部結構的知識。它應該類似於傳遞給pipe的參數:第一個參數是可調用的(函數),其餘參數是參數。假設arguments = [f, a, b, c]。然後JavaScript模式arguments[0].apply(null, [].slice.call(arguments, 1))表示:f(a, b, c)。你可以在sink實現中看到它的使用的幾個地方。

關於實際使用情況。

如果我們需要「鏈」(或「管道」)數據處理,我們可以使用它。例如,如果我們有這樣的代碼:

function f(a, b, previousResult) 
{ 
    return a * b + (previousResult || 0); 
} 

var p = pipeline(). 
    source(f, 1, 1). 
    pipe(f, 2, 10). 
    pipe(f, 3, 100). 
    sink(f, 4, 1000); 

然後將結果(p值)將是4321

在這種特殊情況下,我們需要澄清什麼是d3.geo.jsonSinkd3.geo.jsonSource,但我希望我幫你看看pipeline函數的含義。

+0

我確實在該問題中發佈了該功能的代碼,但源代碼鏈接有幫助 –

+0

@Incodeveritas,我對此功能添加了一些評論。 –

+0

@Incodeveritas,我再次更新了我的答案 - 也許現在它更有用。 –

相關問題