14

我试图画一条线,从一条细线开始,然后逐渐变宽直到结束。我需要绘制半平滑曲线(由几条直线合成),但我在寻找解决此任务的方法时遇到了问题。

这个小提琴显示了我的问题:

http://jsfiddle.net/ZvuQG/1/

当您调用 stroke() 时,当前设置的 lineWidth 用于描边整条线。我的第一个想法是单独绘制每个线段,但是当然,这会在拐角处的线中留下明显的间隙。

我在这里最好的选择是什么?我应该求助于绘制多边形(梯形)来获得正确的角落吗?

有没有更简单的方法?

(编辑:请注意,我并没有尝试实际绘制椭圆或任何其他基本形状;我正在尝试绘制数学函数,使用线条粗细来表示速度)

4

3 回答 3

8

对于那些感兴趣的人,我想出了两个解决我的问题的方法。

第一个想法是将每个点实际绘制为一个角,使用画布绘制一个整齐的角度。可以在以下位置看到演示:

http://jsfiddle.net/7BkyK/2/

var ctx = document.getElementById('canvas1').getContext('2d');
var points = [null, null, null];

for(var i=0; i<24; i++)
{
    var width = 0.5 + i/2;

    var m = 200;

    var x = Math.cos(i/4) * 180;
    var y = Math.sin(i/4) * 140;

    points[0] = points[1];
    points[1] = points[2];
    points[2] = { X:x, Y:y};

    if(points[0] == null)
        continue;

    var px0 = (points[0].X + points[1].X) / 2;
    var py0 = (points[0].Y + points[1].Y) / 2;

    var px1 = (points[1].X + points[2].X) / 2;
    var py1 = (points[1].Y + points[2].Y) / 2;

    ctx.beginPath();
    ctx.lineWidth = width;
    ctx.strokeStyle = "rgba(0,0,0,0.5)";
    ctx.moveTo(m+px0,m+py0);
    ctx.lineTo(m+points[1].X,m+points[1].Y);
    ctx.lineTo(m+px1,m+py1);
    ctx.stroke();
}
​

正如 Shmiddty 所建议的,第二种也是更漂亮的解决方案是使用贝塞尔曲线。事实证明这是一个很好的解决方案:

http://jsfiddle.net/Ssrv9/1/

// 1.
// Varying line width, stroking each piece of line separately
var ctx = document.getElementById('canvas1').getContext('2d');
var points = [null, null, null, null];

for(var i=-1; i<25; i = i +1)
{
    var width = 0.5 + i/2;

    var m = 200;


    var x = Math.cos(i/4) * 180;
    var y = Math.sin(i/4) * 140;

    points[0] = points[1];
    points[1] = points[2];
    points[2] = { X:x, Y:y};

    if(points[0] == null)
        continue;


    var p0 = points[0];
    var p1 = points[1];
    var p2 = points[2];

    var x0 = (p0.X + p1.X) / 2;
    var y0 = (p0.Y + p1.Y) / 2;

    var x1 = (p1.X + p2.X) / 2;
    var y1 = (p1.Y + p2.Y) / 2;

    ctx.beginPath();
    ctx.lineWidth = width;
    ctx.strokeStyle = "black";

    ctx.moveTo(m+x0, m+y0);
    ctx.quadraticCurveTo(m+p1.X, m+p1.Y, m+x1, m+y1);
    ctx.stroke();
}

​</p>

于 2012-10-19T13:59:06.477 回答
2

添加圆形线帽和二次曲线使整个事物看起来更整洁。

例如,请参见此处

于 2012-10-12T09:11:18.583 回答
0

解决此问题的另一种方法是将每个绘图点视为由速度确定的半径圆。

绘制连接这些圆的轮廓边缘的路径(直的或弯曲的,您可以选择),首先在顶部,最后一个圆,然后回到底部的起点。然后在最后填充路径。

当它接近你的绘图点“圆圈”时,这应该会给你一条平滑的线扩展和收缩。

于 2012-10-12T09:22:25.403 回答