我想在画布上以以下方式在圆内画一些线条。
我不知道如何像下面展示的那样画线。但是我有在画布上绘制线条和弧线的基本知识。该怎么做?
我不知道如何像下面展示的那样画线。但是我有在画布上绘制线条和弧线的基本知识。该怎么做?
你可以像评论中建议的那样使用带有控制点的贝塞尔曲线,但是这些可能很难控制(不是说笑话),因为它们不会通过您定义的点,并且您始终需要定义两个控制点。
为了使用实际点实现通过点的线,您需要使用 基数样条。
没有内置支持,但我之前为JavaScript和canvas制作了一个实现(代码可以从这里下载,MIT许可证)。
使用此功能,您只需最少定义三个点(以获得简单的曲线),该函数将负责在点之间绘制平滑曲线并设置张力值。
例如,如果您定义了以下三个点:
var pts = [10,100, 200,50, 390,100];
ctx.beginPath();
ctx.curve(pts);
ctx.stroke();
ctx.curve(pts, 0.8);
将它降低到0.3,会使其变得不那么平滑,如下图所示:
ctx.curve(pts, 0.3);
除了本文档顶部的链接中提到的其他参数外,如果您想要添加超细控制,可以在点数组中拥有“无限”数量的点。
该实现扩展了画布上下文,但是如果您不想使用它,也可以提取该方法并单独使用。
我希望我正确理解了您的绘图... 要在圆形上使用上述功能,您只需要执行以下操作:
假设您希望在-70°至70°之间绘制线条,最多5条,您可以这样做:
var ctx = canvas.getContext('2d'),
cx = canvas.width * 0.5,
cy = canvas.height * 0.5,
pts,
startAngle = -70,
endAngle = 70,
lines = 5,
angle,
range,
steps,
radius = 90,
delta = 15,
x, y,
i;
ctx.lineWidth = 3;
ctx.strokeStyle = '#059';
/// draw arc
ctx.beginPath();
ctx.arc(cx, cy, radius, 0, 2 * Math.PI);
ctx.stroke();
/// calculate angle range normalized to 0 degrees
startAngle = startAngle * Math.PI / 180;
endAngle = endAngle * Math.PI / 180;
range = endAngle - startAngle;
steps = range / (lines + 1);
/// calculate point at circle (vertical only)
for(i = 1; i <= lines; i++) {
pts = [];
/// right side
x = cx + radius * Math.cos(startAngle + steps * i);
y = cy + radius * Math.sin(startAngle + steps * i);
pts.push(x, y);
/// center
pts.push(cx, y + delta * ((y - cy)/ cy));
/// flip for left side
x = cx - (x - cx);
pts.push(x, y);
/// draw curve
ctx.beginPath();
ctx.curve(pts, 0.8);
ctx.stroke();
}
现在只需要尝试不同的值(例如delta)并计算水平行即可。我会把这些留给提问者自己练习:
话虽如此,如果你希望地球更加圆形,你也可以使用一个函数来计算部分椭圆,并将其绘制为线条。这个实现与上面的方法大致相同,但需要使用一个子函数来计算左右两侧之间的椭圆,并使用线条和中心点之间的距离作为半径。
例如:
/// calculate point at circle (vertical only)
for(i = 1; i <= lines; i++) {
pts = [];
/// right side
x = cx + radius * Math.cos(startAngle + steps * i);
y = cy + radius * Math.sin(startAngle + steps * i);
pts.push(cx - radius, cy);
pts.push(cx, y);
pts.push(cx + radius, cy);
/// draw ellipse side
ctx.beginPath();
drawEllipseSide(pts, true);
ctx.stroke();
}
function drawEllipseSide(pts, horizontal) {
var radiusX,
radiusY,
cx, cy,
x, y,
startAngle,
endAngle,
steps = Math.PI * 0.01,
i = 0;
if (horizontal) {
radiusX = Math.abs(pts[4] - pts[0]) * 0.5;
radiusY = pts[3] - pts[1];
cx = pts[2];
cy = pts[1];
startAngle = 0;
endAngle = Math.PI;
x = cx + radiusX * Math.cos(startAngle);
y = cy + radiusY * Math.sin(startAngle);
ctx.moveTo(x, y);
for(i = startAngle + steps; i < endAngle; i += steps) {
x = cx + radiusX * Math.cos(i);
y = cy + radiusY * Math.sin(i);
ctx.lineTo(x, y);
}
}
}
我的代码强迫症作祟 :-P 但是您至少应该有几个选项可供选择。研究代码以了解如何计算垂直线,并采用该方法来计算水平线。
希望这可以帮助您!