2013-07-17 31 views
3

將文字裝配到網站上的圓形上的一種很好的解決方案是什麼,因此它會與圓形的曲線一起流動,而不是矩形的邊界框?在svg或canvas中將文字包裝成圓形

以下是我想要實現的: 頁面上有許多黑色圓圈(固定大小),其中每個都有一個textarea。 將文本輸入到文本區域時,它會出現在黑色圓圈中,並以兩個軸爲中心。 如果輸入的文本太多,該線條變得比圓形半徑長,減去指定的邊距值,則線條會像您期望的那樣從常規包裝中斷開,文本塊仍居中。 靠近頂部或底部的線條當然會比靠近中間的線條短。

文本將具有固定大小,並且當圓圈填充文本時,額外內容不應顯示(如隱藏溢出)。

帶文字的黑色圓圈實際上是泡泡,意思是打印並粘貼在海報上。

是否有任何奇妙的SVG/Canvas庫支持這個或者我將不得不從頭開始指出我們的一種方法?

+0

還有,你試過這麼遠嗎?請分享您遇到問題的代碼。 – K3N

+0

我一直在做一系列不同的實驗,問題不在於代碼本身,而在於方法論。 一個沒有包裝的相當粗糙的版本,需要將HTML元素覆蓋在黑色圓圈的PNG上,並用
標籤替換textarea中的換行符。 這是可以使用的,但不是非常優雅,因爲它缺少包裝到非矩形形狀的元素,而是依賴用戶來分解文本。 – Lowkey

+1

幾個小時前發佈了類似的問題:(http://stackoverflow.com/questions/20913869/wrap-text-within-circle)也許會有一些有趣的答案。 – VividD

回答

10

有一個建議CSS功能調用「排除」,將有可能流入限定區域內的文本:http://www.w3.org/TR/css3-exclusions/

這意味着,SVG和Canvas的路徑可能會被定義爲容器和文本會流/包在容器內。

我確實說過「建議」 - 這是遠離在瀏覽器中成爲現實的一種方式。

但是......

可以使用HTML畫布很容易換一個圈子裏面的文字

enter image description here

你下移可用的寬度上的任何線顯示文本改變圈。

以下是如何確定一個圈中的任何水平線的最大可用寬度

// var r is the radius of the circle 
// var h is the distance from the top of the circle to the horizontal line you’ll put text on 

var maxWidth=2*Math.sqrt(h*(2*r-h)); 

你適合文本行通過測量文本加一個字的寬度的時間,直到你用盡了該行的所有可用寬度。

下面介紹如何使用畫布使用當前context.font測量任何文字:

var width=ctx.measureText(「This is some test text.」).width; 

剩下的就是將文本添加到每個排隊的最大行寬,然後開始一個新行。

如果您更喜歡SVG,則可以使用element.getComputedTextLength方法爲文本度量標準在SVG中執行類似操作。

這裏是代碼和一個小提琴:http://jsfiddle.net/m1erickson/upq6L/

<!doctype html> 
<html lang="en"> 
<head> 

    <style> 
     body{ background-color: ivory; padding:20px; } 
     canvas{ border:1px solid red;} 
    </style> 
    <script src="http://code.jquery.com/jquery-1.9.1.js"></script> 

    <script> 

    $(function() { 

     var canvas=document.getElementById("canvas"); 
     var ctx=canvas.getContext("2d"); 

     var text = "'Twas the night before Christmas, when all through the house, Not a creature was stirring, not even a mouse. And so begins the story of the day of Christmas"; 
     var font="12pt verdana"; 
     var textHeight=15; 
     var lineHeight=textHeight+5; 
     var lines=[]; 

     var cx=150; 
     var cy=150; 
     var r=100; 

     initLines(); 

     wrapText(); 

     ctx.beginPath(); 
     ctx.arc(cx,cy,r,0,Math.PI*2,false); 
     ctx.closePath(); 
     ctx.strokeStyle="skyblue"; 
     ctx.lineWidth=2; 
     ctx.stroke(); 


     // pre-calculate width of each horizontal chord of the circle 
     // This is the max width allowed for text 

     function initLines(){ 

      for(var y=r*.90; y>-r; y-=lineHeight){ 

       var h=Math.abs(r-y); 

       if(y-lineHeight<0){ h+=20; } 

       var length=2*Math.sqrt(h*(2*r-h)); 

       if(length && length>10){ 
        lines.push({ y:y, maxLength:length }); 
       } 

      } 
     } 


     // draw text on each line of the circle 

     function wrapText(){ 

      var i=0; 
      var words=text.split(" "); 

      while(i<lines.length && words.length>0){ 

       line=lines[i++]; 

       var lineData=calcAllowableWords(line.maxLength,words); 

       ctx.fillText(lineData.text, cx-lineData.width/2, cy-line.y+textHeight); 

       words.splice(0,lineData.count); 
      }; 

     } 


     // calculate how many words will fit on a line 

     function calcAllowableWords(maxWidth,words){ 

      var wordCount=0; 
      var testLine=""; 
      var spacer=""; 
      var fittedWidth=0; 
      var fittedText=""; 

      ctx.font=font; 

      for(var i=0;i<words.length; i++){ 

       testLine+=spacer+words[i]; 
       spacer=" "; 

       var width=ctx.measureText(testLine).width; 

       if(width>maxWidth){ 
        return({ 
         count:i, 
         width:fittedWidth, 
         text:fittedText 
        }); 
       } 

       fittedWidth=width; 
       fittedText=testLine; 

      } 

     } 


    }); // end $(function(){}); 

    </script> 
</head> 
<body> 
    <p>Text wrapped and clipped inside a circle</p> 
    <canvas id="canvas" width=300 height=300></canvas> 
</body> 
</html> 
+0

是的,我閱讀了有關排除情況的文章,但只有在金絲雀身上啓用實驗性標誌的解決方案纔沒有完全削減。 上面的代碼給了我一些工作。 如果沒有足夠的文本填充圓圈,我將進行一些調整以使文本始終垂直居中。 – Lowkey

+1

@Lowkey我正在尋找同樣的事情。你是否設法使它始終垂直居中? – yohairosen