在JavaScript Canvas中沿着一条线移动一个点

时间:2011-05-12 22:10:15

标签: javascript math canvas 2d line

假设我有一条线的坐标(25,35 45,65,30,85 - 它将是两部分线)。我需要每帧以恒定的距离沿着那条线移动一个点(汽车)。我怎么能这样做?

4 个答案:

答案 0 :(得分:18)

嘿,所以你的2行有坐标(25,35)(45,65)(30,85),你要移动的点将被放置在这些坐标的第一个(25, 35)并且你希望它移向第二个坐标(45,65)(第一个线段的末尾)。

第一步是获得点移动的方向,方向是点位置和目标位置之间的角度。要找到此角度,您可以使用Math.atan2(),将target position Y - the point position Y作为第一个参数传入,将target position X - the point position X作为第二个参数传入。

var Point = {X: 25, Y: 35};
var Target = {X:45, Y:65};

var Angle = Math.atan2(Target.Y - Point.Y, Target.X - Point.X);

现在获得该角度的正弦和余弦,正弦是沿Y轴移动的值,余弦是在X轴上移动多少。将正弦和余弦乘以您想要移动每帧的距离。

var Per_Frame_Distance = 2;
var Sin = Math.sin(Angle) * Per_Frame_Distance;
var Cos = Math.cos(Angle) * Per_Frame_Distance;

好的,现在剩下要做的就是设置重绘方法,将正弦值添加到点的Y位置,将余弦值添加到每次调用时点的X位置。检查点是否已到达目的地,然后执行相同的过程以移至第二个线段的末尾。

答案 1 :(得分:11)

考虑一下这条线(25,35 45,65)。从开始到结束的向量是(20,30)。要在该方向上移动一个点(x,y),我们可以添加该向量:

V =(20,30) (x,y)=> (x + 20,y + 30)。

如果我们从行的开头开始,我们将在结束时到达。 但这太重要了。我们想要更小但方向相同的东西,所以我们将矢量乘以0.1:

V =(2,3) (x,y)=> (x + 2,y + 3)=> (x + 4,y + 6)=> ...

标准化很方便,即长度为1,我们用它的长度除以:

V => V / | V | =(2,3)/ sqrt(2 2 + 3 2 )=(7.21,10.82)

然后你可以将它乘以你想要的任何步长。

答案 2 :(得分:1)

有时如何将数学公式转换为代码并不是那么明显。以下是沿着一条线移动指定距离的函数的实现。它使用矢量符号:

function travel(x, y, dx, x1, y1, x2, y2)
{
    var point = new Vector(x, y),
        begin = new Vector(x1, y1),
        end = new Vector(x2, y2);
    return end.sub(begin).norm().mul(dx).add(point);
}

class Vector
{
    constructor(x = 0, y = 0) {
        this.x = x;
        this.y = y;
    }

    clone() {
        return new this.constructor(this.x, this.y);
    }

    add(v) {
        this.x += v.x;
        this.y += v.y;
        return this;
    }

    sub(v) {
        this.x = this.x - v.x;
        this.y = this.y - v.y;
        return this;
    }

    mul(x) {
        this.x *= x;
        this.y *= x;
        return this;
    }

    div(x) {
        this.x /= x;
        this.y /= x;
        return this;
    }

    get mag() {
        return Math.sqrt(this.x * this.x + this.y * this.y);
    }

    norm() {
        var mag = this.mag;
        if (mag > 0) {
            this.div(mag);
        }
        return this;
    }
}

没有Vector类的版本:

function travel(x, y, dx, x1, y1, x2, y2)
{
    var a = {x: x2 - x1, y: y2 - y1},
        mag = Math.sqrt(a.x*a.x + a.y*a.y);
    if (mag == 0) {
        a.x = a.y = 0;
    }
    else {
        a.x = a.x/mag*dx;
        a.y = a.y/mag*dx;
    }
    return {x: x + a.x, y: y + a.y};
}

答案 3 :(得分:1)

8年为时已晚,但有人可能会觉得有用。如果不使用像atan,cos,sin和平方根之类的东西,这些方法的速度都快得多。

function getPositionAlongTheLine(x1, y1, x2, y2, percentage) {
    return {x : x1 * (1.0 - percentage) + x2 * percentage, y : y1 * (1.0 - percentage) + y2 * percentage};
}

通过百分比作为介于0和1之间的值,其中0是行的开始,而1是行的结束。

var xy = getPositionAlongTheLine(100, 200, 500, 666, 0.5);
console.log(xy.x, xy.y);