沿着画布上的线放置文本标签

发布于 2024-10-18 10:18:24 字数 218 浏览 0 评论 0原文

我设法使用 html5 在画布上画一条线:

ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();

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

I managed to draw a line on a canvas using html5:

ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();

This works. I now want to "annotate" the line with text. So basically, I want there to be custom (e.g. whatever I pass in) text appearing along the length of the line. The difficulty is that the line can appear in any orientation (e.g. have any slope) so the text needs to be oriented accordingly. Any ideas how to start?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蓝色星空 2024-10-25 10:18:24

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

  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. (已弃用)

I have created an example of this on my website. In general, you want to:

  1. translate the context to the anchor point of the text, then
  2. rotate the context by the amount (in radians) you desire, and then
  3. fillText as normal.

I have included the relevant portion of my example below; I leave it as an exercise to the reader to detect when the text is upside down and handle it as desired.
Edit: view the source on my site for additional code that keeps the text upright and also auto-truncates it.

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();
}

For Firefox only you also have the option of using mozTextAlongPath. (Deprecated)

喜爱纠缠 2024-10-25 10:18:24

我使用了它并且它起作用了 =) 我只是改变了一些东西,以便当我使节点旋转时,标签始终处于易于阅读的位置:

在我的重绘函数中,我放置了这样的内容:

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();
    })          

谢谢,

Dámaris。

I used it and it worked =) I just changed something so that when I make the node spin, the label is always in a good position to be read:

In my redraw function I put something like this:

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();
    })          

Thanks,

Dámaris.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文