посмотри в концеЭффект:
Как примечание, этот эффект был вдохновлен вторым справочником.
Красный шар в центре — это солнце, а бирюзовый шар — это земля. Видно, что орбита Земли представляет собой эллипс, что подтверждает первый из трех законов Кеплера. Он движется быстрее в перигелии и медленнее в афелии, что соответствует здравому смыслу.
Угадайте, сколько времени мне понадобилось, чтобы написать этот эффект?
На это уходит не более получаса, на самом деле реализовать его можно относительно быстро после освоения принципа.
Принцип относительно прост, при условии, что используемый векторный инструмент.
1. Думайте о векторах
В предыдущих статьях этой серии компоненты осей x и y использовались для вычисления физического вектора мяча.
fx = f * Math.cos(angle)
fy = f * Math.sin(angle)
ax = fx / ball.m
ay = fy / ball.m
vx += ax
vy += ay
ball.x += vx
ball.y += vy
В приведенном выше коде f — это сила, m — масса, a — ускорение, а v — скорость. Суффикс — это компонент соответствующего вектора, например, fx — это горизонтальный компонент вектора силы f.
Вышеуказанные операции по существу используют сложение и вычитание начальной школы, и на самом деле не используют векторы или вектора.
Предположим, мы векторpУказывает текущее положение мяча, векторvУказывает текущую скорость, затем положение шарика в следующем кадре — розовый вектор на рисунке ниже. Нет необходимости вычислять компоненты оси X и оси Y отдельно.
Чтобы представить векторный тип данных, мы просто обертываем класс Vector:
class Vector {
constructor(x, y) {
this.x = x
this.y = y
}
scale(n) {
this.x *= n
this.y *= n
return this
}
mag() {
return Math.sqrt(this.x * this.x + this.y * this.y);
}
normalize() {
var m = this.mag()
if (m != 0 && m != 1) {
this.scale(1 / m)
}
return this
}
add(other) {
this.x += other.x
this.y += other.y
return this
}
sub(other) {
this.x -= other.x
this.y -= other.y
return this
}
static add(one, other) {
return new Vector(one.x + other.x, one.y + other.y)
}
static sub(one, other) {
return new Vector(one.x - other.x, one.y - other.y)
}
static dist(one, other) {
var dx = one.x - other.x
var dy = one.y - other.y
return Math.sqrt(dx * dx + dy * dy)
}
}
Эти векторные операции очень просты, например, add означает добавление нового вектора к текущему вектору, mag используется для вычисления размера вектора, scale используется для масштабирования размера вектора, normalize используется для вычисления единичного вектора. и так далее. Хотя нижний слой по-прежнему является компонентами x и y для расчета. Но наименьшая единица нашего мышления — это вектор, который на уровень выше.
Например, предыдущий код представлен в виде вектора:
a = f.scale(1 / ball.m)
v.add(a)
ball.p.add(v)
С векторными инструментами работать с гравитационными формулами легко.
2. Принцип анимации
Затем взгляните на принцип анимации открытия, чтобы убедиться, что он действительно прост.
Все на Земле знают Ньютона.низкий уровень всемирного тяготенияЭто великое открытие:
Любые две частицы притягиваются друг к другу силой в направлении центральной линии. Величина гравитационной силы пропорциональна произведению их массы и обратно пропорциональна квадрату их расстояния и не имеет ничего общего с химическим составом двух объектов и типом среды между ними.
Где G — гравитационная постоянная, мы можем упростить ее до 1 в анимации.
Запишите формулу в виде кода:
var dist = Vector.dist(sun.p, earth.p)
var f = sun.m * earth.m / (dist * dist)
И это все тот же скаляр f, только размер, без направления. Земля гравитацией, направление должно быть обращено к солнцу, и поэтому полный код:
function gravity (sun, earth) {
var dist = Vector.dist(sun.p, earth.p)
var f = sun.m * earth.m / (dist * dist)
var vec = Vector.sub(sun.p, earth.p)
return vec.normalize().scale(f)
}
Причина, по которой она заключена в функцию, заключается в том, что гравитационная сила между Землей и Солнцем постоянно меняется. Направление вектора vec направлено к солнцу, возьмите для него единичный вектор и масштабируйте его до f. Таким образом, конечным результатом является гравитационный вектор.
Поэтому основной код движения Земли легко написать:
var g = gravity(sun, earth)
var a = g.scale(1 / earth.m)
v.add(a)
earth.p.add(v)
Это основные принципы, а остальное — реализация.
3. Реализация
И солнце, и земля используют модель маленькой сферы:
class Ball{
constructor() {
this.p = new Vector(0, 0)
this.m = 0
this.radius = 20
this.color = 'white'
}
draw(context) {
context.save()
context.translate(this.p.x, this.p.y)
context.beginPath()
context.arc(0, 0, this.radius, 0, 2 * Math.PI)
context.fillStyle = this.color
context.fill()
context.restore()
}
}
Этот код не первый раз в этой серии, разница лишь в том, что исходные this.x и this.y заменены вектором this.p.
Инициализируйте Солнце и Землю:
var sun = new Ball()
sun.radius = 30
sun.color = 'red'
sun.p = new Vector(canvas.width / 2, canvas.height / 2)
sun.m = 1000
var earth = new Ball()
earth.radius = 3
earth.color = 'aqua'
earth.p = new Vector(canvas.width / 2 + 100, canvas.height / 2 + 80)
earth.m = 1
Соотношение масс Солнца и Земли составляет 1000:1. Положение Земли является случайным выбором.
Далее идет основной код принципа, где мы предполагаем, что солнце не движется.
;(function drawFrame() {
window.requestAnimationFrame(drawFrame)
context.clearRect(0, 0, canvas.width, canvas.height)
var g = gravity(sun, earth)
var a = g.scale(1 / earth.m)
v.add(a)
earth.p.add(v)
earth.draw(context)
sun.draw(context)
})()
Важным моментом здесь является то, что Земля должна иметь начальную скорость v.
Скорость движения Земли по орбите будет разной для разных размеров и направлений. Если начальная скорость равна вектору 0, Земля врежется в Солнце из-за гравитации:
Конечно, после того, как земля ударилась о солнце, оно не разрушилось, но земля быстро отдалилась от солнца. Поскольку скорость относительно высока, гравитационная сила никогда не сможет повернуть ее назад. На самом деле это «гравитационная рогатка» в романе о трех телах.
Давайте сделаем размер солнца меньше и выбирайте скорость как:
var v = new Vector(-0.3, 1)
Эффект гравитационной рогатки будет лучше:
Если выбор скорости:
var v = new Vector(-0.8, 1).scale(2.2)
Мяч будет двигаться по круговой орбите:
Вы можете настроить параметры по своему желанию, попробовать другие ситуации и увидеть эффект.
Нажмите, чтобы просмотреть окончательный эффект и полный код.
Спасибо, что вы здесь, надеюсь, это поможет.
Эта статья закончилась.
Ниже приводится введение в эту серию.
В конце 2019 года я установил флаг для изучения технологии анимации холста в 2020 году.
(QR-код на картинке — мой единственный идентификатор WeChat. Если вы хотите добавить его, обратите внимание на [самородки].)
В этой серии я хочу написать некоторые общие знания об анимации.Эта статья 5-я, и длина может варьироваться. Для получения дополнительной информации, пожалуйста, проверьте мою личную страницу, или"Каталог серий".
Из-за проблемы с местом, по прошлому опыту, количество лайков будет не слишком большим, ведь всем нравится лайкать статьи, которые невозможно прочитать за короткое время. Ну мне кажется тоже так. ^_^
На самом деле написание статей в основном для себя, это свидетельство самосовершенствования. Может быть, лучше иметь такое отношение.
К тому же про технологию холста я прочитал 3 книги полностью. Это выше основ.
1.«Основная технология холста HTML5»
2.«Основы анимации HTML5+JavaScript»
3.Руководство по программированию WebGL
Некоторые статьи в этой серии могут ссылаться на систему знаний в ней.Для некоторых предметных знаний консенсуса, если есть частичное сходство, мы можем только сказать: "Я узнал это своими собственными навыками, как это может считаться плагиатом..." .
Шучу, источник идеи можно назвать одним предложением или одним предложением. Мне особенно нравится абзац в статье «Элитный дневной класс»:
Что касается содержания статьи, API холста, эту серию можно не вводить по одному, прошу прощения за новичков. У MDN он есть, очень подробный. При этом будет кратко упомянуто то, что встречается в статье. Основное ядро состоит в том, чтобы объяснить некоторое личное понимание знаний на уровне навыков и принципов. Кроме того, я также планирую проанализировать принципы реализации некоторых крутых анимаций на codepen.Если будет время, я могу проанализировать несколько анимационных движков, конечно, все они 2D.
Еще раз спасибо, что дочитали до этого места. Увидимся в следующей статье.