在画布上沿着一条线放置文本标签

4
我使用HTML5成功在画布上绘制了一条线:
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();

这个可以工作。我现在想要在这条线上“注释”文本。所以基本上,我希望自定义(例如我传递的任何内容)文本沿着线的长度出现。困难在于,该线可以以任何方向出现(例如具有任何斜率),因此文本需要相应地定位。有什么想法如何开始吗?

2个回答

15

我在我的网站上创建了一个示例。一般来说,您需要:

  1. 将上下文平移到文本的锚点处,然后
  2. 按所需角度(弧度制)旋转上下文,然后
  3. 像往常一样使用fillText

我在下面包含了我示例的相关部分;检测文本何时上下颠倒并进行相应处理是读者的练习任务编辑:在我的网站上查看源代码,获取保持文本直立且自动截断的其他代码。

function drawLabel( ctx, text, p1, p2, alignment, padding ){
  if (!alignment) alignment = 'center';
  if (!padding) padding = 0;

  var dx = p2.x - p1.x;
  var dy = p2.y - p1.y;   
  var p, pad;
  if (alignment=='center'){
    p = p1;
    pad = 1/2;
  } else {
    var left = alignment=='left';
    p = left ? p1 : p2;
    pad = padding / Math.sqrt(dx*dx+dy*dy) * (left ? 1 : -1);
  }

  ctx.save();
  ctx.textAlign = alignment;
  ctx.translate(p.x+dx*pad,p.y+dy*pad);
  ctx.rotate(Math.atan2(dy,dx));
  ctx.fillText(text,0,0);
  ctx.restore();
}

仅适用于Firefox,您还可以使用mozTextAlongPath选项。 (已弃用)


我已经阅读了你的帖子中链接的用例并且也自己实现了一遍,除了填充不像预期的那样工作外,其他都很好。我期望它表示文本和线之间的间隙。它的预期目的是什么? 还有谁能帮忙控制文本和线之间的间隙? - xodeeq

0

我用过它并且它工作了 =) 我只是更改了一些东西,当我让节点旋转时,标签始终处于良好位置以便阅读:

在我的重绘函数中,我加入了类似以下的内容:

particleSystem.eachEdge(function(edge, pt1, pt2){
      // edge: {source:Node, target:Node, length:#, data:{}}
      // pt1:  {x:#, y:#}  source position in screen coords
      // pt2:  {x:#, y:#}  target position in screen coords
      // draw a line from pt1 to pt2

     var dx = (pt2.x - pt1.x);
     var dy = (pt2.y - pt1.y);
     var p, pad;
     var alignment = "center";


      //ctx.label(edge.data.role,dx,dy,5,90,14);
      ctx.strokeStyle = "rgba(0,0,0, .333)";
      ctx.lineWidth = 1;
      ctx.beginPath();
      ctx.moveTo(pt1.x, pt1.y);
      ctx.lineTo(pt2.x, pt2.y);
      ctx.stroke();


     p = pt1;
     pad = 1/2;
     ctx.save();
 ctx.textAlign = alignment;
 ctx.translate(p.x+dx*pad,p.y+dy*pad);
     if(dx < 0)
     {
     ctx.rotate(Math.atan2(dy,dx) - Math.PI);  //to avoid label upside down
     }
     else
     {
     ctx.rotate(Math.atan2(dy,dx));

 }
     ctx.fillStyle = "black"
     ctx.fillText(edge.data.role,0,0);

 ctx.restore();
    })          

谢谢,

达玛丽丝。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接