2013-10-22 54 views
3

我已經看到D3.js- Voronoi Tessellation的例子。但我希望把一些文字中的每個多邊形,而不是圓的,這是我的js代碼:如何用D3.js限制Voronoi圖中的多邊形文本?

var width = 600, height = 400; 

var vertices = d3.range(20).map(function(d){ 
    return [Math.random() * width, Math.random() * height] 
}); 

var voronoi = d3.geom.voronoi(); 

var svg = d3.select("body").append("svg") 
    .attr("width", width) 
    .attr("height", height); 

path = svg.append("g").selectAll("path"); 

svg.selectAll("info") 
    .data(vertices.slice(1)) 
    .enter().append("text") 
    .attr("transform", function(d) { 
     return "translate(" + d + ")"; 
    }) 
    .text("someText") 
    .attr("shape-rendering","crispEdges") 
    .style("text-anchor","middle"); 

redraw(); 

function redraw(){ 
    path = path 
     .data(voronoi(vertices), polygon); 

    path.exit().remove(); 

    path.enter().append("path") 
     .attr("class", function(d, i) {return "q" + (i % 9) + "-9";}) 
     .attr("d", polygon); 

    path.order(); 
} 

function polygon(d){ 
    return "M" + d.join("L") + "Z"; 
} 

我有一個的jsfiddle爲這裏的基本示例: my voronoi code

現在,我希望每個多邊形的文本位於多邊形的中心,並且不要與多邊形的邊框交叉。如果多邊形沒有足夠的空間來容納全部文本,只需包含它的第一部分! 讓我知道如果有什麼我可以做的解決這個問題,謝謝! PS:我很抱歉我的英語,是的,它太可憐了! :)

+0

件文成多邊形是不平凡的。首先,您需要找出文本的最佳位置(因爲某些多邊形非常不規則),然後確定文本的大小,多邊形的大小以及它們相交的位置。然後根據這個縮短文本。剪輯路徑可能會更容易。 –

+0

@LarsKotthoff你能告訴我一些關於剪輯路徑的文章嗎? :) – CodingMonkey

+0

看看例如[這裏](http://www.svgbasics.com/clipping.html)。 –

回答

3

看看這個例子http://bl.ocks.org/mbostock/6909318,你可能想把文本放置在多邊形質心而不是用來確定voronoi鑲嵌的種子(點)。

這應該解決您的大部分佈局問題。

自動縮放文本以適應是有點困難,如果你願意縮放和旋轉,你可以使用類似如下的技術來確定該點的行的文本長度:

https://mathoverflow.net/questions/116418/find-longest-segment-through-centroid-of-2d-convex-polygon

然後你需要確定線的角度。我有一個插件,應該有所幫助: http://bl.ocks.org/stephen101/7640188/3ffe0c5dbb040f785b91687640a893bae07e36c3

最後,您需要縮放和旋轉文本以適合。爲了確定文本的寬度使用getBBox()的文本元素:

var text = svg.append("svg:text") 
    .attr("x", 480) 
    .attr("y", 250) 
    .attr("dy", ".35em") 
    .attr("text-anchor", "middle") 
    .style("font", "300 128px Helvetica Neue") 
    .text("Hello, getBBox!"); 

var bbox = text.node().getBBox(); 

然後,可以使用前面計算的縮放和旋轉文本的角度:

text.attr("transform", "rotate(40) scale(7)") 

我很樂意給一個完整的例子,但這是相當多的工作,以使其正確。

還有其他選項,以達到同樣的效果,但他們都不是簡單的(例如,你可以退火相似D3的方式做了桑基佈局佈局)