画一条线有两个不同大小的末端

时间:2015-03-31 20:16:17

标签: javascript canvas

如何使用画布将两条不同尺寸的线条划分?

我正在使用canvas绘制一条线,我希望宽度为30并逐渐(按比例)减小到15的尺寸,所以它在行尾就达到了15。

我认为,如果我将context.lineWidth设置在两个地方(开始和结束),它可能会起作用。



<!DOCTYPE HTML>
<html>
  <head>
    <style>
      body {
        margin: 0px;
        padding: 0px;
      }
    </style>
  </head>
  <body>
    <canvas id="myCanvas" width="578" height="200"></canvas>
    <script>
      var canvas = document.getElementById('myCanvas');
      var context = canvas.getContext('2d');

      context.beginPath();
      context.moveTo(100, 150);
      context.lineWidth = 30;
      context.lineTo(450, 50);
      context.lineWidth = 15;
      context.stroke();
    </script>
  </body>
</html>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:3)

我曾经想过建立这样一个可变宽度的线,我结束了自己的解决方案,并写了一篇博文。
我在这里复制它的第一部分,圆形版本也可以在这里找到: https://gamealchemist.wordpress.com/2013/08/28/variable-width-lines-in-html5-canvas/


html5中的可变宽度行

一旦我们意识到我们需要绘制的不是一条线,那么绘制这样一条[可变宽度]线很容易:实际上它是一个多边形。

如果我们想要绘制的线段是(A,B),情况如下:

enter image description here

我们想要绘制的是A1,A2,B2,B1多边形。

如果我们将N称为法线向量(在方案上绘制),并且将W1和W2分别称为A和B中的宽度,我们有:
A1 = A + N * w1 / 2
A2 = A - N * w1 / 2
B1 = B + N * w2 / 2
B2 = B - N * w2 / 2

那么我们如何找到这个法向量N?
数学说如果(x,y)定义向量V,则其法向量坐标为(-y,x) N,因此AB的法向量将具有( - (yB - yA),(xB - xA))作为坐标。
但是这个向量有一个烦人的事情:它取决于AB长度,而不是 我们想要的是:我们需要对这个向量进行标准化,即将它的标准长度设置为1,所以当我们稍后将这个向量乘以w1 / 2时,我们会得到正确的长度向量。

矢量归一化是通过将矢量的x和y除以矢量长度来完成的。 因为使用phytagore定理找到长度,所以得到2个正方形,一个平方根,最后2个除以找到归一化向量N:

// computing the normalized vector normal to AB
length = Math.sqrt( sq (xB-xA) + sq (yB - yA) ) ;
Nx     =  -  (yB - yA) / length ;
Ny     =     (xB - xA) / length ;  

现在我们可以计算四个点,让我们用多边形线将它们连接起来,然后填充得到的形状:这是我们的可变宽度线段!

以下是javascript代码:

// varLine : draws a line from A(x1,y1) to B(x2,y2)
// that starts with a w1 width and ends with a w2 width.
// relies on fillStyle for its color.
// ctx is a valid canvas's context2d.
function varLine(ctx, x1, y1, x2, y2, w1, w2) {
    var dx = (x2 - x1);
    var dy = (y2 - y1);
    w1 /= 2;  w2 /= 2; // we only use w1/2 and w2/2 for computations.
    // length of the AB vector
    var length = Math.sqrt(sq(dx) + sq(dy));
    if (!length) return; // exit if zero length
    dx /= length ;    dy /= length ;
    var shiftx = - dy * w1   // compute AA1 vector's x
    var shifty =   dx * w1   // compute AA1 vector's y
    ctx.beginPath();
    ctx.moveTo(x1 + shiftx, y1 + shifty);
    ctx.lineTo(x1 - shiftx, y1 - shifty); // draw A1A2
    shiftx =  - dy * w2 ;   // compute BB1 vector's x
    shifty =    dx * w2 ;   // compute BB1 vector's y
    ctx.lineTo(x2 - shiftx, y2 - shifty); // draw A2B1
    ctx.lineTo(x2 + shiftx, y2 + shifty); // draw B1B2
    ctx.closePath(); // draw B2A1
    ctx.fill();    
}

因此,让我们看一个小例子的结果:在一个圆圈内绘制具有漂亮的hsl颜色的可变宽度段:

enter image description here

(关于@MarkE&#39; s(有趣)关于链接线段的评论,我担心这是一个相当困难的目标,因为根据线段长度/ w1 / w2 /角度在段之间存在许多具体情况。使用力场和行进立方体完全解决了它,但我担心这完全偏离主题!! :-))