简体   繁体   English

在HTML5画布中绘制箭头曲线

[英]Drawing Arrow Head Curves in HTML5 Canvas

I am attempting to draw the 3 arrows below. 我试图绘制下面的3个箭头。 I can draw the top one correctly but I cannot draw the other 2 arrow heads correctly. 我可以正确地绘制顶部,但我无法正确绘制其他2个箭头。 I am using HTML5 Canvas to draw these arrows. 我正在使用HTML5 Canvas绘制这些箭头。

在此输入图像描述

The problem occurs with my arcTo calls. 我的arcTo调用出现问题。 I just cannot get the correct curve to occur for some reason. 由于某种原因,我无法得到正确的曲线。 Maybe I should be using a Bezier curve? 也许我应该使用Bezier曲线? Would anyone be able to tell me what HTML5/Javascript functions I use to produce the above arrow heads? 有人能告诉我我使用什么HTML5 / Javascript函数来生成上面的箭头?

Can you provide an example of how to achieve the above arrow heads? 你能提供一个如何实现上述箭头的例子吗?

Heres the JSFiddle to show whats going wrong: http://jsfiddle.net/hJX8X/ 继承人JSFiddle显示出错: http//jsfiddle.net/hJX8X/

<canvas id="testCanvas" width="400px" height="400px">

</canvas>
<script type="text/javascript">
<!--
    var canvas = document.getElementById("testCanvas");
    var dc     = canvas.getContext("2d");

    // Points which are correct (when I draw straight lines its a perfect arrow
    var width    = 400;
    var height   = 100;
    var arrowW   = 0.35 * width;
    var arrowH   = 0.75 * height;
    var p1       = {x: 0,              y: (height-arrowH)/2};
    var p2       = {x: (width-arrowW), y: (height-arrowH)/2};
    var p3       = {x: (width-arrowW), y: 0};
    var p4       = {x: width,          y: height/2};
    var p5       = {x: (width-arrowW), y: height};
    var p6       = {x: (width-arrowW), y: height-((height-arrowH)/2)};
    var p7       = {x: 0,              y: height-((height-arrowH)/2)};

    dc.clearRect(0, 0, canvas.width, canvas.height);
    dc.fillStyle = "#FF0000";

    dc.beginPath();

    dc.moveTo(p1.x, p1.y);
    dc.lineTo(p2.x, p2.y);
    dc.lineTo(p3.x, p3.y);      
    dc.moveTo(p3.x, p3.y);
    dc.arcTo(p3.x, p3.y, p4.x, p4.y, 50);
    dc.moveTo(p4.x, p4.y);
    dc.arcTo(p4.x, p4.y, p5.x, p5.y, 50);
    dc.moveTo(p5.x, p5.y);
    dc.lineTo(p6.x, p6.y);
    dc.lineTo(p7.x, p7.y);

    dc.closePath();
    dc.fill();

    /* Draw arrow without curves
    dc.moveTo(p1.x, p1.y);
    dc.lineTo(p2.x, p2.y);
    dc.lineTo(p3.x, p3.y);      
    dc.lineTo(p4.x, p4.y);  
    dc.lineTo(p5.x, p5.y);
    dc.lineTo(p6.x, p6.y);
    dc.lineTo(p7.x, p7.y);
    */
-->
</script>

So we've got this path that makes an arrow. 所以我们有了这条带箭头的道路。 I've annotated it: 我注释了它:

dc.moveTo(p1.x, p1.y);
dc.lineTo(p2.x, p2.y); // end of main block
dc.lineTo(p3.x, p3.y); // topmost point     
dc.lineTo(p4.x, p4.y); // endpoint 
dc.lineTo(p5.x, p5.y); // bottommost point 
dc.lineTo(p6.x, p6.y); // end at bottom point 
dc.lineTo(p7.x, p7.y);

We really want to keep it as similar as possible except we want to get to the endpoint (and back) in a different way than just a straight line. 我们真的希望保持尽可能相似,除非我们想要以不同于直线的方式到达端点(和返回)。 We absolutely do not want to use any moveTo commands except the first one. 我们绝对不想使用除第一个之外的任何moveTo命令。 That really confounds things and makes them hard to understand. 这真的让事情变得混乱,让人难以理解。 I'd also avoid using arcTo unless you really need part of an arc (like in a pie) because its fairly confusing compared to the other path commands. 我也避免使用arcTo,除非你真的需要弧的一部分(比如在饼图中),因为它与其他路径命令相比相当混乱。

So we'll use quadratic curves which are like beziers but only have one control point, making them pretty simple. 所以我们将使用像beziers一样的二次曲线,但只有一个控制点,这使得它们非常简单。 They work by specifying a control point like this (on the left) . 它们通过指定这样的控制点(左侧)来工作

So we take the same exact arrow code and insert two quadratic beziers to make a skinny arrow. 所以我们采用相同的箭头代码并插入两个二次贝塞尔曲线来制作一个瘦箭头。 We want the control points to be sorta "inside" the mass of the arrow to make the quadratics bend inwards: 我们希望控制点在箭头的质量“内部”排序,以使正方形向内弯曲:

dc.moveTo(p1.x, p1.y);
dc.lineTo(p2.x, p2.y); // end of main block
dc.lineTo(p3.x, p3.y); // topmost point
// control point is based on p3 (topmost point)
dc.quadraticCurveTo(p3.x + 20, p3.y + 30, p4.x, p4.y); // endpoint 
// control point is based on p5 (bottommost point)
dc.quadraticCurveTo(p5.x + 20, p5.y - 30, p5.x, p5.y); // bottommost point 
dc.lineTo(p6.x, p6.y); // end at bottom point 
dc.lineTo(p7.x, p7.y);

Or a fat one, we put the control point at the same height as the topmost and bottommost point, and around the same X as the endpoint: 或者是一个胖的,我们将控制点放在与最高点和最低点相同的高度,并且与端点在同一个X周围:

dc.beginPath();
// Draw arrow without curves
dc.moveTo(p1.x, p1.y);
dc.lineTo(p2.x, p2.y); // end of main block
dc.lineTo(p3.x, p3.y); // topmost point
// control point is based on p3 (topmost point)
dc.quadraticCurveTo(p3.x + 120, p3.y, p4.x, p4.y); // endpoint 
// control point is based on p5 (bottommost point)
dc.quadraticCurveTo(p5.x + 120, p5.y, p5.x, p5.y); // bottommost point 
dc.lineTo(p6.x, p6.y); // end at bottom point 
dc.lineTo(p7.x, p7.y);

Live example here: http://jsfiddle.net/Yp7DM/ 这里的实例: http//jsfiddle.net/Yp7DM/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM