我正在尝试绘制一条以细线开头的线,然后逐渐扩大直到结束。我需要绘制半光滑曲线(由几条直线组成的复合曲线),我在找到解决此任务的方法时遇到了问题。
这个小提琴显示了我的问题:
调用stroke()时,当前设置的lineWidth用于描边整行。我的第一个想法是单独绘制每个线条,但当然,这会在角落的线条上留下明显的间隙。
这里我最好的选择是什么?我应该采用绘制多边形(梯形)来使角落正确吗?
有更简单的方法吗?
(编辑:请注意,我并没有尝试实际绘制椭圆或任何其他基本形状;我正在尝试绘制数学函数,使用线条粗细来表示速度)
答案 0 :(得分:6)
对于那些感兴趣的人,我已经为我的问题提出了两个解决方案。
第一个想法是将每个点实际绘制为一个角,使用画布绘制一个整齐的角度。可以在以下位置看到演示:
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建议的第二个更漂亮的解决方案是使用贝塞尔曲线。事实证明这是一个很好的解决方案:
// 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();
}
答案 1 :(得分:2)
添加圆形线帽和二次曲线使整个事物看起来更加整洁。
例如,请参阅here。
答案 2 :(得分:0)
另一种解决方法是将每个绘图点视为由速度确定的半径圆。
绘制连接这些圆的轮廓边缘的路径(直线或弯曲,您的选择),首先在顶部,绕过最后一个并返回到底部的开始。然后填写最后的路径。
这会给你一条平滑的线条扩展和收缩,因为它接近你的情节点'圆圈'。