Расширенные анимации
В предыдущей главе мы сделали несколькобазовых анимаций и узнали, как можно двигать вещи. В этой части мы более подробно рассмотрим само движение и собираемся добавить некоторую физику, чтобы сделать наши анимации более продвинутыми.
Рисование мяча
Мы собираемся использовать шар для наших анимационных исследований, поэтому давайте сначала нарисуем этот шар наcanvas
. Нам нужен следующий код.
<canvas width="600" height="300"></canvas>
Как обычно, нам нужен контекст рисования. Чтобы нарисовать шар, мы создадим объектball
, который содержит свойства и методdraw()
, чтобы нарисовать его наcanvas
.
var canvas = document.getElementById("canvas");var ctx = canvas.getContext("2d");var ball = { x: 100, y: 100, radius: 25, color: "blue", draw: function () { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); ctx.closePath(); ctx.fillStyle = this.color; ctx.fill(); },};ball.draw();
Здесь нет ничего особенного, шар на самом деле представляет собой простой круг и рисуется с помощью методаarc()
.
Добавление скорости
Теперь, когда у нас есть шар, мы готовы добавить базовую анимацию, как мы узнали из последнейглавы этого урока. Опять же,window.requestAnimationFrame()
помогает нам контролировать анимацию. Мяч перемещается, добавляя вектор скорости в положение. Для каждого кадра мы такжеочищаем холст, чтобы удалить старые круги из предыдущих кадров.
var canvas = document.getElementById("canvas");var ctx = canvas.getContext("2d");var raf;var ball = { x: 100, y: 100, vx: 5, vy: 2, radius: 25, color: "blue", draw: function () { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); ctx.closePath(); ctx.fillStyle = this.color; ctx.fill(); },};function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); ball.draw(); ball.x += ball.vx; ball.y += ball.vy; raf = window.requestAnimationFrame(draw);}canvas.addEventListener("mouseover", function (e) { raf = window.requestAnimationFrame(draw);});canvas.addEventListener("mouseout", function (e) { window.cancelAnimationFrame(raf);});ball.draw();
Границы
Без какого-либо граничного коллизионного тестирования наш мяч быстро выбегает из холста. Нам нужно проверить, не находятся лиx
иy
положения шара вне размеров холста и не инвертируют направление векторов скорости. Для этого мы добавим следующие проверки в методdraw
:
if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) { ball.vy = -ball.vy;}if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) { ball.vx = -ball.vx;}
Первое демо
Посмотрим, как он выглядит в действии. Переместите мышь на холст, чтобы запустить анимацию.
<canvas width="600" height="300"></canvas>
var canvas = document.getElementById("canvas");var ctx = canvas.getContext("2d");var raf;var ball = { x: 100, y: 100, vx: 5, vy: 2, radius: 25, color: "blue", draw: function () { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); ctx.closePath(); ctx.fillStyle = this.color; ctx.fill(); },};function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); ball.draw(); ball.x += ball.vx; ball.y += ball.vy; if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) { ball.vy = -ball.vy; } if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) { ball.vx = -ball.vx; } raf = window.requestAnimationFrame(draw);}canvas.addEventListener("mouseover", function (e) { raf = window.requestAnimationFrame(draw);});canvas.addEventListener("mouseout", function (e) { window.cancelAnimationFrame(raf);});ball.draw();
Ускорение
Чтобы сделать движение более реальным, вы можете играть со скоростью, например так:
ball.vy *= 0.99;ball.vy += 0.25;
Это замедляет вертикальную скорость каждого кадра, так что мяч будет просто отскакивать от пола в конце.
<canvas width="600" height="300"></canvas>
var canvas = document.getElementById("canvas");var ctx = canvas.getContext("2d");var raf;var ball = { x: 100, y: 100, vx: 5, vy: 2, radius: 25, color: "blue", draw: function () { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); ctx.closePath(); ctx.fillStyle = this.color; ctx.fill(); },};function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); ball.draw(); ball.x += ball.vx; ball.y += ball.vy; ball.vy *= 0.99; ball.vy += 0.25; if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) { ball.vy = -ball.vy; } if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) { ball.vx = -ball.vx; } raf = window.requestAnimationFrame(draw);}canvas.addEventListener("mouseover", function (e) { raf = window.requestAnimationFrame(draw);});canvas.addEventListener("mouseout", function (e) { window.cancelAnimationFrame(raf);});ball.draw();
Скользящий эффект
До сих пор мы использовали методclearRect
, когда очищали предыдущий кадр. Если заменить этот метод наfillRect
с полу-прозрачным стилем, можно легко создать эффект скольжения.
ctx.fillStyle = "rgba(255, 255, 255, 0.3)";ctx.fillRect(0, 0, canvas.width, canvas.height);
<canvas width="600" height="300"></canvas>
var canvas = document.getElementById("canvas");var ctx = canvas.getContext("2d");var raf;var ball = { x: 100, y: 100, vx: 5, vy: 2, radius: 25, color: "blue", draw: function () { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); ctx.closePath(); ctx.fillStyle = this.color; ctx.fill(); },};function draw() { ctx.fillStyle = "rgba(255, 255, 255, 0.3)"; ctx.fillRect(0, 0, canvas.width, canvas.height); ball.draw(); ball.x += ball.vx; ball.y += ball.vy; ball.vy *= 0.99; ball.vy += 0.25; if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) { ball.vy = -ball.vy; } if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) { ball.vx = -ball.vx; } raf = window.requestAnimationFrame(draw);}canvas.addEventListener("mouseover", function (e) { raf = window.requestAnimationFrame(draw);});canvas.addEventListener("mouseout", function (e) { window.cancelAnimationFrame(raf);});ball.draw();
Управление мышью
Чтобы получить некоторый контроль над мячом, мы можем заставить его следовать за нашей мышью, например, с помощью событияmousemove
. Событиеclick
отпускает мяч и позволяет ему снова прыгать.
<canvas width="600" height="300"></canvas>
var canvas = document.getElementById("canvas");var ctx = canvas.getContext("2d");var raf;var running = false;var ball = { x: 100, y: 100, vx: 5, vy: 1, radius: 25, color: "blue", draw: function () { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); ctx.closePath(); ctx.fillStyle = this.color; ctx.fill(); },};function clear() { ctx.fillStyle = "rgba(255, 255, 255, 0.3)"; ctx.fillRect(0, 0, canvas.width, canvas.height);}function draw() { clear(); ball.draw(); ball.x += ball.vx; ball.y += ball.vy; if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) { ball.vy = -ball.vy; } if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) { ball.vx = -ball.vx; } raf = window.requestAnimationFrame(draw);}canvas.addEventListener("mousemove", function (e) { if (!running) { clear(); ball.x = e.clientX; ball.y = e.clientY; ball.draw(); }});canvas.addEventListener("click", function (e) { if (!running) { raf = window.requestAnimationFrame(draw); running = true; }});canvas.addEventListener("mouseout", function (e) { window.cancelAnimationFrame(raf); running = false;});ball.draw();
Переместите шар с помощью мыши и отпустите его одним щелчком.
Breakout
В этой короткой главе описаны некоторые приёмы создания продвинутой анимации. Но их гораздо больше! Как насчёт того, что бы добавить доску, кирпичи и превратить это демо в игруBreakout? В разделеРазработка игр собраны материалы об играх.