2013-07-17 27 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