Допустим, у меня есть координаты линии (25,35 45,65, 30,85 - это будет линия из двух частей). Мне нужно перемещать точку (автомобиль) вдоль этой линии на постоянном расстоянии каждый кадр. Как я могу это сделать?
Перемещение точки вдоль строки в холсте JavaScript
Ответ 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);