在画布标签上绘制箭头

47 javascript drawing html5-canvas

我想使用canvas标签javascript绘制一个箭头.我使用二次函数制作了它,但是我在计算箭头的旋转角度时遇到了问题......

有人知道这个吗?

谢谢

小智 81

就这么简单,我可以得到它.您必须自己添加context.beginPath()并自己附加context.stroke():

ctx = document.getElementById("c").getContext("2d");
ctx.beginPath();
canvas_arrow(ctx, 10, 30, 200, 150);
canvas_arrow(ctx, 100, 200, 400, 50);
canvas_arrow(ctx, 200, 30, 10, 150);
canvas_arrow(ctx, 400, 200, 100, 50);
ctx.stroke();


function canvas_arrow(context, fromx, fromy, tox, toy) {
  var headlen = 10; // length of head in pixels
  var dx = tox - fromx;
  var dy = toy - fromy;
  var angle = Math.atan2(dy, dx);
  context.moveTo(fromx, fromy);
  context.lineTo(tox, toy);
  context.lineTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
  context.moveTo(tox, toy);
  context.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
}
Run Code Online (Sandbox Code Playgroud)

这是一个示例:http: //stuff.titus-c.ch/arrow.html

  • 对于更大的线宽,只需添加`context.moveTo(tox,toy);``context.lineTo(tox,toy);`(参见:http://i.imgur.com/jMOsLM9.png) (3认同)

Ste*_*ard 27

好的,所以当我试图自己解决这个问题时,这页上的第一个答案对我有很大的帮助,尽管正如其他人已经说过的那样,如果你的线宽大于1px,你会得到有趣的形状.其他人建议的解决方案几乎可以解决,但在尝试使用更宽的箭头时仍然存在一些问题.经过几个小时的游戏后,我能够将上述解决方案与我自己的一些修补结合起来,得出以下代码,可以绘制任意厚度的箭头而不会扭曲箭头形状.

function drawArrow(fromx, fromy, tox, toy){
                //variables to be used when creating the arrow
                var c = document.getElementById("myCanvas");
                var ctx = c.getContext("2d");
                var headlen = 10;

                var angle = Math.atan2(toy-fromy,tox-fromx);

                //starting path of the arrow from the start square to the end square and drawing the stroke
                ctx.beginPath();
                ctx.moveTo(fromx, fromy);
                ctx.lineTo(tox, toy);
                ctx.strokeStyle = "#cc0000";
                ctx.lineWidth = 22;
                ctx.stroke();

                //starting a new path from the head of the arrow to one of the sides of the point
                ctx.beginPath();
                ctx.moveTo(tox, toy);
                ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7));

                //path from the side point of the arrow, to the other side point
                ctx.lineTo(tox-headlen*Math.cos(angle+Math.PI/7),toy-headlen*Math.sin(angle+Math.PI/7));

                //path from the side point back to the tip of the arrow, and then again to the opposite side point
                ctx.lineTo(tox, toy);
                ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7));

                //draws the paths created above
                ctx.strokeStyle = "#cc0000";
                ctx.lineWidth = 22;
                ctx.stroke();
                ctx.fillStyle = "#cc0000";
                ctx.fill();
            }
Run Code Online (Sandbox Code Playgroud)

这是我在程序中使用的代码.我发现消除失真问题的关键是继续从箭头尖端到一侧点,到另一侧点,回到尖端,然后回到第一个侧面点,然后做一个填.这纠正了箭头的形状.

希望这可以帮助!


Noi*_*art 8

这是另一种绘制箭头的方法。它从这里使用三角形方法:https : //stackoverflow.com/a/8937325/1828637

一点辅助功能。

function canvas_arrow(context, fromx, fromy, tox, toy, r){
    var x_center = tox;
    var y_center = toy;

    var angle;
    var x;
    var y;

    context.beginPath();

    angle = Math.atan2(toy-fromy,tox-fromx)
    x = r*Math.cos(angle) + x_center;
    y = r*Math.sin(angle) + y_center;

    context.moveTo(x, y);

    angle += (1/3)*(2*Math.PI)
    x = r*Math.cos(angle) + x_center;
    y = r*Math.sin(angle) + y_center;

    context.lineTo(x, y);

    angle += (1/3)*(2*Math.PI)
    x = r*Math.cos(angle) + x_center;
    y = r*Math.sin(angle) + y_center;

    context.lineTo(x, y);

    context.closePath();

    context.fill();
}
Run Code Online (Sandbox Code Playgroud)

这是在行的开始和结尾绘制箭头的演示。

function canvas_arrow(context, fromx, fromy, tox, toy, r){
    var x_center = tox;
    var y_center = toy;

    var angle;
    var x;
    var y;

    context.beginPath();

    angle = Math.atan2(toy-fromy,tox-fromx)
    x = r*Math.cos(angle) + x_center;
    y = r*Math.sin(angle) + y_center;

    context.moveTo(x, y);

    angle += (1/3)*(2*Math.PI)
    x = r*Math.cos(angle) + x_center;
    y = r*Math.sin(angle) + y_center;

    context.lineTo(x, y);

    angle += (1/3)*(2*Math.PI)
    x = r*Math.cos(angle) + x_center;
    y = r*Math.sin(angle) + y_center;

    context.lineTo(x, y);

    context.closePath();

    context.fill();
}
Run Code Online (Sandbox Code Playgroud)
var can = document.getElementById('c');
var ctx = can.getContext('2d');

ctx.lineWidth = 10;
ctx.strokeStyle = 'steelblue';
ctx.fillStyle = 'steelbllue'; // for the triangle fill
ctx.lineJoin = 'butt';

ctx.beginPath();
ctx.moveTo(50, 50);
ctx.lineTo(150, 150);
ctx.stroke();

canvas_arrow(ctx, 50, 50, 150, 150, 10);
canvas_arrow(ctx, 150, 150, 50, 50, 10);

function canvas_arrow(context, fromx, fromy, tox, toy, r){
	var x_center = tox;
	var y_center = toy;
	
	var angle;
	var x;
	var y;
	
	context.beginPath();
	
	angle = Math.atan2(toy-fromy,tox-fromx)
	x = r*Math.cos(angle) + x_center;
	y = r*Math.sin(angle) + y_center;

	context.moveTo(x, y);
	
	angle += (1/3)*(2*Math.PI)
	x = r*Math.cos(angle) + x_center;
	y = r*Math.sin(angle) + y_center;
	
	context.lineTo(x, y);
	
	angle += (1/3)*(2*Math.PI)
	x = r*Math.cos(angle) + x_center;
	y = r*Math.sin(angle) + y_center;
	
	context.lineTo(x, y);
	
	context.closePath();
	
	context.fill();
}
Run Code Online (Sandbox Code Playgroud)


Fab*_*ger 7

你可以做:

ctx.save();
ctx.translate(xOrigin, yOrigin);
ctx.rotate(angle);
 // draw your arrow, with its origin at [0, 0]
ctx.restore();
Run Code Online (Sandbox Code Playgroud)


Aik*_*wai 6

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

ctx.clearRect(0, 0, canvas.width, canvas.height);	
arrow({x: 10, y: 10}, {x: 100, y: 170}, 10);
arrow({x: 40, y: 250}, {x: 10, y: 70}, 5);


function arrow (p1, p2, size) {
  var angle = Math.atan2((p2.y - p1.y) , (p2.x - p1.x));
  var hyp = Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));

  ctx.save();
  ctx.translate(p1.x, p1.y);
  ctx.rotate(angle);

  // line
  ctx.beginPath();	
  ctx.moveTo(0, 0);
  ctx.lineTo(hyp - size, 0);
  ctx.stroke();

  // triangle
  ctx.fillStyle = 'blue';
  ctx.beginPath();
  ctx.lineTo(hyp - size, size);
  ctx.lineTo(hyp, 0);
  ctx.lineTo(hyp - size, -size);
  ctx.fill();

  ctx.restore();
}
Run Code Online (Sandbox Code Playgroud)
<canvas id = "canvas" width = "300" height = "400"></canvas>
Run Code Online (Sandbox Code Playgroud)


Ant*_*nko 6

Typescript 版本,当线宽 >> 1 时带有固定箭头提示

function canvas_arrow( context, fromx, fromy, tox, toy ) {
    const dx = tox - fromx;
    const dy = toy - fromy;
    const headlen = Math.sqrt( dx * dx + dy * dy ) * 0.3; // length of head in pixels
    const angle = Math.atan2( dy, dx );
    context.beginPath();
    context.moveTo( fromx, fromy );
    context.lineTo( tox, toy );
    context.stroke();
    context.beginPath();
    context.moveTo( tox - headlen * Math.cos( angle - Math.PI / 6 ), toy - headlen * Math.sin( angle - Math.PI / 6 ) );
    context.lineTo( tox, toy );
    context.lineTo( tox - headlen * Math.cos( angle + Math.PI / 6 ), toy - headlen * Math.sin( angle + Math.PI / 6 ) );
    context.stroke();
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Cli*_*int 0

您可以推动矩阵,旋转它,绘制箭头,然后弹出矩阵。