javascript - 如何在 Canvas 中画线

标签 javascript jquery html canvas html5-canvas

我想按照以下方式在 Canvas 上的圆圈内画一些线。

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

enter image description here

最佳答案

您可以按照带有控制点的评论中的建议使用贝塞尔曲线,但是,这些曲线可能很难控制(没有双关语),因为它们不通过您定义的点,您总是需要定义两个控制点。

为了使用实际点通过点获得一条线,您需要使用基数样条

没有对这些的内置支持,但不久前我为 JavaScript 和 Canvas 实现了这个(代码可以下载 from here,MIT 许可证)。

有了这个,您可以简单地定义三个点作为最小值(以获得一条简单的曲线),该函数将负责在具有设定张力值的点之间绘制一条平滑的曲线。

例如,如果您定义了以下三点:

var pts = [10,100, 200,50, 390,100];

你显然只会得到一个 simple poly-line like this如果我们想说明要点(用于比较):

Lines

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

Cardinal spline

以下代码生成上述曲线(没有红点表示点坐标):

ctx.beginPath();
ctx.curve(pts);
ctx.stroke();

现在只需移动点(特别是中心点),曲线就会采用。为用户添加张力 slider 可能是一个优势:

Increasing the tension例如 0.8 给你这个结果:

ctx.curve(pts, 0.8);

Higher tension

lowering it例如 0.3 将降低平滑度:

ctx.curve(pts, 0.3);

Lower tension

还有其他参数(请参阅顶部的文档链接),如果您想添加超精细控制,您可以在点数组中拥有“无限”数量的点。

该实现扩展了 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();
}

这会导致:

Globe

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

导致这个(我在最后的图画中做了一点欺骗,以便更清楚地了解(没有双关语)如果你继续沿着这些线(也没有双关语,我被双关语诅咒)最终结果会是什么)此处):

Globe

Fiddle here

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

希望这对您有所帮助!

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

相关文章:

javascript - 计算不包括节假日和周末的 future 日期

javascript - 用 JavaScript 编写 HTML 代码可以吗?

javascript - 如何使用 setInterval 和 clearInterval?

javascript - 在 javascript/jquery 中删除字符串的一部分?

javascript - Karma/Chrome 的警告和错误

javascript - 滚动 div - 带有 javascript 的 css

javascript - 如何使用 jquery 获取表中的祖 parent 文本

html - YouTube 视频无法在 HTML5 的 <video> 中进行流式传输

html - 为什么 <button> 中的绝对定位与 <div> 中的绝对定位不同

html - 如何选择标签a的文字