2012-10-11 75 views
11

我试图画出一条线条,该线条以细线开始,然后逐渐变宽直至结束。我需要绘制半光滑的曲线(由几条直线组成的复合曲线),并且在找到解决此任务的方法时遇到问题。在HTML画布上以不断变化的线条宽度绘制线条

这拨弄显示我的问题:

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

当你调用stroke(),当前设置的线宽用于中风的整条生产线。我的第一个想法是单独画出每一行,但当然这会在角落处留下明显的空白。

这里我最好的选择是什么?我是否应该采用绘制多边形(梯形)来获得正确的角?

有没有更简单的方法?

(编辑:请注意,我不是要实际绘制椭圆形或任何其他基本形状,我想绘制数学函数,利用线条的粗细代表速度)

+4

你最好的选择可能是将要使用'bezierCurveTo'或'quadraticCurveTo'和'fill',而不是'stroke',它会使数学复杂化,但它可能是获得理想结果的唯一方法。我已经能够通过绘制多个省略号和每一步抵消/缩小它们来实现类似但不同的效果:http://jsfiddle.net/Shmiddty/ZvuQG/3/ – Shmiddty

回答

4

对于那些有兴趣的人,我提出了两个解决我的问题。

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

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(); 
} 

2

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

例如参见here

+0

这是一个很好的解决方案,应该已经工作了,根据到我在问题中指定的参数。但是,我没有说我想控制线条的不透明度,在这种情况下,圆角看起来不那么好: http://jsfiddle.net/X2Vm7/ – Valdemar

0

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

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

这应该会给你一个平滑的线条扩大和缩小,因为它接近你绘制点'圆'。