2012-09-21 111 views
3

我正在使用Raphael.js在圖像上創建多邊形(或實際封閉的路徑)。我想把文字放在多邊形裏面。有什麼方法可以創建一個文本元素,然後調整其大小和位置,以便整個事物將在多邊形的範圍內?在SVG或Raphael.js的路徑或多邊形內寫入文本

是否至少有任何算法可以給我很好的猜測,我可以手動調整?

+0

這些多邊形有多複雜?您能提供一個或兩個最極端的例子嗎? –

+0

它們可以是任意複雜的。它們都應該是封閉的多邊形。他們通常會有四面或更多面。它們可能是凸多邊形,但是至少適用於凹多邊形的算法會很有用。 – Joe

回答

3

好的,我在一天中給了這個想法,最後有機會把一個小小的演示代碼放在一起。從很多方面來看,它是明顯不完美的,但可能形成一個很好的起始位置,而且似乎與我的大部分隨機生成的多邊形一起工作得很好。

第1部分:將文本置於多邊形的中心。使用邊框證明似地差強人意,所以不是我發明了一種技術來平均所有的點在一個給定的路徑container

  // Determine the *weighted* center of this figure 
      var segments = Raphael.parsePathString(container.attr('path')); 
      var count = 0, sum_x = 0, sum_y = 0; 
      for (var i = 0; i < segments.length; i++) 
      { 
       if (segments[i][0] == 'L' || segments[i][0] == 'M') 
       { 
        count++; 
        sum_x += segments[i][1]; 
        sum_y += segments[i][2]; 
       } 
      } 

      var cx = sum_x/count, cy = sum_y/count; 

2部分:碰撞檢測。我需要一種機制來檢查給定的對象是否在當前形狀內。懶惰,我只是在創建畫布之前擴展了Raphael元素對象。

 Raphael.el.isObjectInside = function(obj) 
     { 
      var box = obj.getBBox(); 
      return this.isPointInside(box.x, box.y) 
         && 
        this.isPointInside(box.x2, box.y) 
         && 
        this.isPointInside(box.x, box.y2) 
         && 
        this.isPointInside(box.x2, box.y2); 
     } 

3部分:迭代大小。基本上,我們使用上面生成的座標並將其應用於生成的標籤文本。我們減少了一次規模每次迭代,直到我們去某個閾值之下,在這一點上我的代碼只是放棄了(你可能不應該):

  var s = 1.0; 
      if (ibox.width >= cbox.width * 0.7) 
      { 
       s = (cbox.width * 0.7)/ibox.width; 
      } 

      while (s > 0.1) 
      { 
       insert.attr({ transform: [ "S", s, s, ibox.x + ibox.width/2, ibox.y + ibox.height/2, "T", 
       if (container.isObjectInside(insert)) 
        return; 
       s *= 0.65; 
      } 

      console.log("Warning: NOT a clean fit"); 

而且結果看起來適用於大多數的純粹隨機的多邊形我扔了它。我敢肯定,它的計算量要比需要的要多得多。我的代碼是here - 只需點擊多邊形就可以生成一個新的。

快樂編碼。