2014-08-27 53 views
2

我正在嘗試用相同數量的段補間2條路徑。我使用的邁克·博斯托克這裏介紹的方法:https://gist.github.com/mbostock/3916621d3js - 2條路徑之間的轉換

svg.append("path") 
    .attr("transform", "translate(180,150)scale(2,2)") 
    .attr("d", d0) 
    .call(transition, d0, d1); 

function transition(path, d0, d1) { 
    path.transition() 
     .duration(2000) 
     .attrTween("d", pathTween(d1, 4)) 
     .each("end", function() { d3.select(this).call(transition, d1, d0); }); 
} 

function pathTween(d1, precision) { 
    return function() { 
    var path0 = this, 
     path1 = path0.cloneNode(), 
     n0 = path0.getTotalLength(), 
     n1 = (path1.setAttribute("d", d1), path1).getTotalLength(); 

    // Uniform sampling of distance based on specified precision. 
    var distances = [0], i = 0, dt = precision/Math.max(n0, n1); 
    while ((i += dt) < 1) distances.push(i); 
    distances.push(1); 

    // Compute point-interpolators at each distance. 
    var points = distances.map(function(t) { 
     var p0 = path0.getPointAtLength(t * n0), 
      p1 = path1.getPointAtLength(t * n1); 
     return d3.interpolate([p0.x, p0.y], [p1.x, p1.y]); 
    }); 

    return function(t) { 
     return t < 1 ? "M" + points.map(function(p) { return p(t); }).join("L") : d1; 
    }; 
    }; 
} 

它提供了很好的效果,但是我現在面臨一個愚蠢的問題。 我想找到一種方法將第一條路徑中的細分與第二條路徑中的細分相關聯,以獲得更好的補間效果。

例如,這裏:http://jsfiddle.net/2brqoo5p/1/ 2路徑具有相似的形狀,但補間比它可能要複雜得多。有沒有辦法來解決這個問題?

非常感謝

+0

也許你可以弄清楚如何繪製第一條路徑'd0',其條款與'd1'相同。即按照與d1中出現的順序相同的順序,使用一系列曲線和直線指定'd0',但點的數值不同。由於'd0'是一個圓,所以每條線將結束於其結束之前的曲線的同一點(即線的長度爲0)。這樣d3可能「知道」如何正確插入它。 – meetamit 2014-08-28 04:27:23

回答

0

恕我直言...

你可能會找不到任何公用事業/ libaries /等,會爲你做到這一點。你會 必須寫你自己的。或等待有人爲你做。或者付錢給別人。

我可以想象這個問題的唯一解決方案是相當乏味的。如果我找到時間 ,我可能會寫一個演示並更新這個答案。沒有承諾, 雖然。事實上,這個代碼似乎對鏈接中的演示 等閉環很有用。

這是僞代碼的想法。不過,這是相當強大的力量。

# convert both SVG path `d` attributes from strings to arrays of points 
list_1 = convert('#path1') 
list_2 = convert('#path2') 

min_dist = 9999 
min_pt_set = {} 

for each point in list_1 -> (p1) 
    for each point in list_2 -> (p2) 
     # find the pair of points with the least distance between them 
     if (min_dist > dist(p1, p2)) 
      min_dist = dist(p1, p2) 
      min_pt_set = {p1, p2} 

# reorder list_1 so that p1 is the first element. 
# reorder list_2 so that p2 is the first element. 

# convert both lists back into svg path strings 

# write the path strings back to the svg `d` attributes. 

重新排序後,您可能需要某種方向檢查。如果路徑 定義爲相反的方向,則可能需要將 的操作顛倒一條路徑。

我不知道任何算法,將適用於所有情況。你選擇 將可能取決於你編碼的情況。您可以嘗試'最少 平方和'或者可能只是檢查與p1和p2相鄰的點並解決最小距離 。

我希望有人比我有更好的解決方案。這是一個有趣的 問題。

另請參見:

  1. http://www.w3.org/TR/SVG/paths.html
  2. Scripting <path> data in SVG (reading and modifying) - 提到解析SVG路徑的方法。
+0

這個解決方案假設有一系列用線連接的點(使用路徑'l'指令),而鏈接的例子也包含曲線('c'指令)。考慮到這一點會使解決方案更加複雜。 – meetamit 2014-08-28 04:21:37

+0

我在我的答案中考慮過曲線。根據SVG規範,曲線指定了端點。該解決方案既不插入直線也不插入曲線;它只檢查端點。如果需要更準確的數據,那麼適應性抽樣可能是一條可行的路線。 – 2014-08-28 14:55:41