5

将文本拟合到网站上的圆圈的一个好的解决方案是什么,所以它会随着圆圈的曲线而不是矩形边界框流动?

这就是我想要实现的目标:页面上有许多黑色圆圈(大小固定),每个圆圈旁边都有一个文本区域。当文本输入到文本区域时,它会出现在黑色圆圈中,它位于两个轴的中心。如果输入的文本过多,则该行变得比圆的半径长,减去指定的边距值,则该行将像您期望的常规换行一样中断,而文本块仍然居中。当然,靠近顶部或底部的线会比靠近中间的线短。

文本将具有固定大小,并且当圆圈充满文本时,不应显示额外内容(如溢出隐藏)。

带有文字的黑色圆圈实际上是气泡,用于打印并粘在海报上。

是否有任何出色的 SVG/Canvas 库支持这一点,还是我必须从头开始寻找我们的方法?

4

1 回答 1

13

有一个提议的 CSS 功能称为“排除”,可以在定义的区域内流动文本:http: //www.w3.org/TR/css3-exclusions/

这意味着 SVG 和 Canvas 路径可能被定义为容器,并且文本将在容器内流动/包装。

我确实说过“提议的”——它离在浏览器中成为现实还有一段距离。

然而...

您可以使用 html canvas 轻松地将文本包裹在一个圆圈内

在此处输入图像描述

当您向下移动圆圈时,可用于在任何行上显示文本的宽度会发生变化。

这是确定圆上任何水平线的最大可用宽度的方法

// 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,您可以在 SVG 中使用 element.getComputedTextLength 方法对文本度量执行类似操作。

这是代码和小提琴: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>
于 2013-07-18T06:46:23.980 回答