Перемещение точки вдоль строки в холсте JavaScript

Допустим, у меня есть координаты линии (25,35 45,65, 30,85 - это будет линия из двух частей). Мне нужно перемещать точку (автомобиль) вдоль этой линии на постоянном расстоянии каждый кадр. Как я могу это сделать?

Ответ 1

Рассмотрим прямую (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

Эй, поэтому у вас есть координаты (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, а Косинус - сколько двигаться по оси Х. Умножьте синус и косинус на расстояние, на которое вы хотите переместить каждый кадр.

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

Хорошо, теперь остается только настроить метод перерисовывания, в котором вы добавляете синус в позицию точки Y и косинус в позицию точки X при каждом вызове. Проверьте, прибыла ли точка к месту назначения, затем выполните тот же процесс, чтобы перейти к концу второго сегмента линии.

Ответ 3

Иногда это не так очевидно, как перевести математическую формулу в код. Ниже приведена реализация функции, которая перемещает заданное расстояние по линии. Он использует векторную нотацию:

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 class:

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

Ответ 4

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