我想以下列方式在 Canvas 上的圆圈内绘制一些线条。

我不知道如何绘制如下所示的线条。但我有在 Canvas 上画线和弧的基本知识。如何进行?

最佳答案

您可以使用带有控制点的评论中建议的贝塞尔曲线,但是,这些可能很难控制(没有双关语),因为它们不会通过您定义的点,并且您总是需要定义两个控制点。
为了使用实际点实现通过点的线,您需要使用 基数样条
没有对这些的内置支持,但不久前我为 JavaScript 和 Canvas 做了一个实现(代码可以下载 from here ,MIT 许可证)。
有了这个,您可以简单地将三个点定义为最小值(以获得简单的曲线),该函数将负责在具有设定张力值的点之间绘制平滑曲线。
例如,如果您定义了以下三点:

var pts = [10,100, 200,50, 390,100];
如果我们想说明要点(用于比较),您显然只会得到 simple poly-line like this :

使用具有相同三个点 would give you this 的基数样条:

以下代码生成上述曲线(没有显示点坐标的红点):
ctx.beginPath();
ctx.curve(pts);
ctx.stroke();
现在只需移动点(特别是中心点),曲线就会采用。为用户添加张力滑块可能是一个优势:
Increasing the tension 到例如 0.8 给你这个结果:
ctx.curve(pts, 0.8);

lowering it 到例如 0.3 将降低平滑度:
ctx.curve(pts, 0.3);

还有其他参数(请参阅顶部的链接以获取文档),如果您想添加超精细控制,您可以在点数组中拥有“无限”数量的点。
该实现扩展了 Canvas 上下文,但如果您心虚的话,您可以提取该方法并单独使用它。 :-)
为一个圆实现这个
我希望我在这里正确解释了您的绘图……要将上面的内容用于圆圈,您只需要执行以下操作:
  • 定义范围,即要绘制线条的圆的边。
  • 定义步骤,即。每行之间的空间。

  • 假设您想在 -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();
    }
    
    这将导致:

    Fiddle here
    现在只是处理值(例如增量)并计算水平行的问题 - 我将把它作为 OP 的练习:
    使用椭圆边绘制线条
    话虽如此-如果您希望地球更圆,圆:-S,您还可以使用函数来计算椭圆的一部分并将其绘制为线。 If 与上面的实现大致相同,但有一个子函数来计算左侧和右侧之间的椭圆,使用线和中点之间的差异作为半径。
    例如:
    /// 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);
            }
        }
    }
    
    结果是(我在最终图纸中作弊了一点,以便更清晰地了解最终结果(没有双关语),如果您继续按照此处给出的这些行(也没有双关语,我被双关语诅咒)给出的最终结果):

    Fiddle here
    我的代码强制症开始了 :-P 但你至少应该有一些选择。研究代码以了解如何计算垂直线并将其用于水平线。
    希望这可以帮助!

    关于javascript - 如何在 Canvas 上画线,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21846480/

    10-12 12:17
    查看更多