2

假设我有 {x:10, y:20} 和 {x:100, y:40},如果我想画一条从 10,20 开始到 100,40 结束的线,我会这样做:

 context.beginPath();
 context.moveTo(10, 20);
 context.lineTo(100, 40);
 context.stroke();

但是,如果我想在它们之间画一条线怎么办?那就是线比点之间的空间长,但它跨越两个点?

4

2 回答 2

2

您可以使用“逆”插值 - 我的意思是,不是用 [0.0, 1.0] 的分数插入一条线,而是可以使用负值或值 > 1 来获得该线的“外部”:

这个在线演示

在此处输入图像描述

代码很简单,您使用 x 和 y 集并用 delta 对它们进行插值,这里是 0 和 1 之间的小数值,其中 1 是其中一个点之外的双倍长度:

function extLine(x1, y1, x2, y2, delta) {

    var ox1 = x1 + (x2 - x1) * -delta,
        ox2 = x1 + (x2 - x1) * (1 + delta),
        oy1 = y1 + (y2 - y1) * -delta,
        oy2 = y1 + (y2 - y1) * (1 + delta);

    ctx.beginPath();
    ctx.moveTo(ox1, oy1);
    ctx.lineTo(ox2, oy2);

    /// for the demo a couple of markers for the original points        
    ctx.rect(x1 - 2, y1 - 2, 5, 5);
    ctx.rect(x2 - 2, y2 - 2, 5, 5);

    ctx.stroke();
}

您可以计算线的长度,而不是作为增量的分数,然后从该结果中获取分数,这样您就可以以像素数延长线。

这是一个版本,您可以改为提供像素数:

function extLine2(x1, y1, x2, y2, pixels) {

    /// calc fraction based on line length and added pixels        
    var xd = x2 - x1,
        yd = y2 - y1,
        len = Math.sqrt(xd * xd + yd * yd),
        delta = pixels / len,

        /// as before
        ox1 = x1 + (x2 - x1) * -delta,
        ox2 = x1 + (x2 - x1) * (1 + delta),
        oy1 = y1 + (y2 - y1) * -delta,
        oy2 = y1 + (y2 - y1) * (1 + delta);

    ctx.beginPath();
    ctx.moveTo(ox1, oy1);
    ctx.lineTo(ox2, oy2);

    ctx.rect(x1 - 2, y1 - 2, 5, 5);
    ctx.rect(x2 - 2, y2 - 2, 5, 5);

    ctx.stroke();
}
于 2013-08-07T22:02:19.363 回答
0

使用以下几种方法之一画一条更长的线:

  1. 将线与画布的边界相交以获得端点
  2. 将线与“更正交”的画布边界相交,即如果 x 差的绝对值小于 y 差的绝对值,则与底部和顶部边界相交,否则与垂直边界线相交
  3. 将直线延长一个固定且足够大的差分向量倍数
  4. 将线延伸到差异向量的倍数,使得该延伸具有固定且已知的大小

其中哪一个最合适取决于您的应用程序。你能依赖最大的画布尺寸,还是最小的点距离?如果不是,那么交叉选项会更稳健,而第二个选项的工作量更少。

于 2013-08-07T21:46:04.910 回答