谁能告诉我如何在javascript中从一个项目到另一个项目绘制任意角度的曲线?

发布于 2024-09-30 14:36:02 字数 2317 浏览 0 评论 0原文

仅作为上下文,我使用 html5、css 和 jquery。

我希望能够在网页上的两个元素之间绘制带有箭头的曲线。我几乎已经明白了,但就是无法专注于数学来绘制箭头。可能只是对画布小部件的操作让我着迷。

这是我现在使用的 javascript。当然感觉很漫长,但除了那些讨厌的箭头之外,它似乎完成了工作。

“影响”变量是稍微改变线条,这样如果有多条线,它们将显示一条在另一条后面。

  var start = $('#firstobject');
  var last = $('#lastobject');
  var stpos = start.position();
  var lastpos = last.position();
  var influence = Math.random*20+5;
  var maxx = Math.max(stpos.left,lastpos.left);
  var minx = Math.min(stpos.left,lastpos.left);
  var maxy = Math.max(stpos.top,lastpos.top);
  var miny = Math.min(stpos.top,lastpos.top);
  var w = maxx - minx;
  var h = maxy - miny;
  var cname = "samplename";
  var cpad = 30;
  var cstr = "<canvas id='"+cname+"' class='huntgroupcanvas' style='z-index:2;position:absolute;left:"+(0+minx-cpad)+"px;top:"+(0+miny-cpad)+"px;' id='"+cname+"' width="+(2*cpad+w)+" height="+(2*cpad+h)+"></canvas>"
  start.before(cstr);
  var canvas = document.getElementById(cname);
  var ctx = canvas.getContext("2d");
  var dx = stpos.left - lastpos.left;
  var dy = stpos.top - lastpos.top;
  var dir = dy/dx;
  var sx,sy,ex,ey;
  if (dir<0) {
    ex=w+cpad;
    ey=cpad;
    sx=cpad;
    sy=h+cpad;
  } else {
    ex=w+cpad;
    ey=h+cpad;
    sx=cpad;
    sy=cpad;
  }

  ctx.lineWidth=1;
  ctx.strokeStyle = '#000';
  ctx.beginPath();
  ctx.moveTo(sx,sy);
  ctx.quadraticCurveTo(((w/2)-(h/2))+cpad-influence,((h/2)-(w/2))+cpad,ex,ey);
  ctx.stroke();
  if (st==i-1) {
    first=0;
    ctx.beginPath();
    if (dx<0) {
      ctx.arc(sx,sy,6,0,Math.PI*2,0);
    } else {
      ctx.arc(ex,ey,6,0,Math.PI*2,0);
    }
    ctx.stroke();
  }

 /* Here's where I've been trying to draw the arrowheads.
  * I know that I can get the slope of the line like so:
    var m = (y2-y1)/(x2-x1);
  * I know I can get the angle in radians as
    var angle=Math.atan(m);
  * I'm trying to use rotation to draw the arrowhead
 */
      ctx.save();
      ctx.beginPath();
      angle = Math.atan(dir);
      if (dx<0) {
        sx=ex;
        sy=ey;
        angle = Math.atan(-dir);
      }
      ctx.moveTo(sx,sy);
      ctx.translate(sx,sy);
      ctx.rotate(angle - 0.05);
      ctx.lineTo(20,0);
      ctx.rotate(angle + 0.05);
      ctx.lineTo(20,0);
      ctx.closePath();
      ctx.fill();
      ctx.restore();

Just for context, I'm using html5, css, and jquery.

I'd like to be able to draw curved lines with arrowheads between two elements on a web page. I've nearly got it, but just can't wrap my head around the maths to draw the arrow heads. Could just be the manipulation of the canvas widget that's getting me.

Here's the javascript I'm using at the minute. It certainly feels the long way around, but it seems to get the job done except for those pesky arrowheads.

The 'influence' variable is to vary the lines a bit so that if there are multiple lines they will show one behind the other.

  var start = $('#firstobject');
  var last = $('#lastobject');
  var stpos = start.position();
  var lastpos = last.position();
  var influence = Math.random*20+5;
  var maxx = Math.max(stpos.left,lastpos.left);
  var minx = Math.min(stpos.left,lastpos.left);
  var maxy = Math.max(stpos.top,lastpos.top);
  var miny = Math.min(stpos.top,lastpos.top);
  var w = maxx - minx;
  var h = maxy - miny;
  var cname = "samplename";
  var cpad = 30;
  var cstr = "<canvas id='"+cname+"' class='huntgroupcanvas' style='z-index:2;position:absolute;left:"+(0+minx-cpad)+"px;top:"+(0+miny-cpad)+"px;' id='"+cname+"' width="+(2*cpad+w)+" height="+(2*cpad+h)+"></canvas>"
  start.before(cstr);
  var canvas = document.getElementById(cname);
  var ctx = canvas.getContext("2d");
  var dx = stpos.left - lastpos.left;
  var dy = stpos.top - lastpos.top;
  var dir = dy/dx;
  var sx,sy,ex,ey;
  if (dir<0) {
    ex=w+cpad;
    ey=cpad;
    sx=cpad;
    sy=h+cpad;
  } else {
    ex=w+cpad;
    ey=h+cpad;
    sx=cpad;
    sy=cpad;
  }

  ctx.lineWidth=1;
  ctx.strokeStyle = '#000';
  ctx.beginPath();
  ctx.moveTo(sx,sy);
  ctx.quadraticCurveTo(((w/2)-(h/2))+cpad-influence,((h/2)-(w/2))+cpad,ex,ey);
  ctx.stroke();
  if (st==i-1) {
    first=0;
    ctx.beginPath();
    if (dx<0) {
      ctx.arc(sx,sy,6,0,Math.PI*2,0);
    } else {
      ctx.arc(ex,ey,6,0,Math.PI*2,0);
    }
    ctx.stroke();
  }

 /* Here's where I've been trying to draw the arrowheads.
  * I know that I can get the slope of the line like so:
    var m = (y2-y1)/(x2-x1);
  * I know I can get the angle in radians as
    var angle=Math.atan(m);
  * I'm trying to use rotation to draw the arrowhead
 */
      ctx.save();
      ctx.beginPath();
      angle = Math.atan(dir);
      if (dx<0) {
        sx=ex;
        sy=ey;
        angle = Math.atan(-dir);
      }
      ctx.moveTo(sx,sy);
      ctx.translate(sx,sy);
      ctx.rotate(angle - 0.05);
      ctx.lineTo(20,0);
      ctx.rotate(angle + 0.05);
      ctx.lineTo(20,0);
      ctx.closePath();
      ctx.fill();
      ctx.restore();

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

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

发布评论

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

评论(1

旧瑾黎汐 2024-10-07 14:36:02

有很多代码需要阅读,但在生成箭头角度时,您似乎弄乱了三角学。看一下 atan2 函数,它接受一个 2D 向量并将其转换为角度。所以你会想使用angle=Math.atan2(dy,dx)

That is a lot of code to read, but it would seem that you are messing up your trigonometry when generating the angle of the arrowhead. Take a look at the atan2 function, it takes a 2D vector and converts it to it's angle. So you would want to use angle=Math.atan2(dy,dx)

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