Javascript как создать движущийся объект
Перейти к содержимому

Javascript как создать движущийся объект

  • автор:

Как с помощью js сделать анимацию движения объектов в рандомном направлении?

6064b741f1104543973927.png

Нужно что б они двинались в рандомном направлении где-то в пределах фиксированой ширины +-
Нашел вот такой пример https://codepen.io/monsmado/details/bGEdaLB
Но там две огромные библиотеки.Хотелось бы без них обойтись, есть ли у кого то идеи, как лучше сделать.Максимум использовать небольшую одну библиотеку

  • Вопрос задан более двух лет назад
  • 595 просмотров

6 комментариев

Средний 6 комментариев

А что мешает сделать position : absolute и начинать их двигать по x и y рандомно в пределах допустимых значений? Линейная геометрия y=k*x+c не или по по формуле окружности или квадратичная функция

stetxems @stetxems Автор вопроса

Rerurk, через css,Они и так Absolute.Но я думал с помощью JS сделать.Чтоб это выглядело как то красиво.Хотя б пример,а то пока не сильно понимаю как правильно сделать , что б работало нормально через js

stetxems, блин, вы хотите что бы за вас это кто то сделал? Ну это через магазин только же
stetxems @stetxems Автор вопроса
Rerurk, я сюда пришел за помощью а не решением.Спасибо за помощь!
stetxems, так я не понял, чем вам мой алгоритм не угодил то?

twobomb

Чё ты паришься, пропиши конкретные пути используя CSS, будто бы кто-то там будет запоминать как оно двигалось. Проще и производительнее

Решения вопроса 0
Ответы на вопрос 1
Сергей Соколов @sergiks Куратор тега JavaScript

Для каждого объекта выбирать случайную точку внутри допустимой области. С каждым кадром к ней приближается 2-я точка. Ко 2-й так же стремится 3-я, и т.д — цепочка из, к примеру, 5 точек. Объект последний, в хвосте. Такая цепочка делает движение плавным, хотя цель выбирается случайно. Когда приближается ближе, чем X, выбирается новое случайное положение для 1-й точки.

p.s. вообще особенности анимации должен был подробно описать дизайнер.

Ответ написан более двух лет назад
Нравится 1 1 комментарий
stetxems @stetxems Автор вопроса

Он не ставил каких то конкретных задач.Сказал хочет видеть что-то похожее.То что я скинул в примере.Но я не хочу реализововать с помощью библиотек.Буду пробовать ваш вариант)

Ваш ответ на вопрос

Войдите, чтобы написать ответ

javascript

  • JavaScript
  • +4 ещё

Что за файл и что в нем?

  • 1 подписчик
  • час назад
  • 39 просмотров

JavaScript-анимации

С помощью JavaScript-анимаций можно делать вещи, которые нельзя реализовать на CSS.

Например, движение по сложному пути с временной функцией, отличной от кривой Безье, или canvas-анимации.

Использование setInterval

Анимация реализуется через последовательность кадров, каждый из которых немного меняет HTML/CSS-свойства.

Например, изменение style.left от 0px до 100px – двигает элемент. И если мы будем делать это с помощью setInterval , изменяя на 2px с небольшими интервалами времени, например 50 раз в секунду, тогда изменения будут выглядеть плавными. Принцип такой же, как в кино: 24 кадров в секунду достаточно, чтобы создать эффект плавности.

Псевдокод мог бы выглядеть так:

let timer = setInterval(function() < if (animation complete) clearInterval(timer); else increase style.left by 2px >, 20); // изменять на 2px каждые 20ms, это около 50 кадров в секунду

Более детальная реализация этой анимации:

let start = Date.now(); // запомнить время начала let timer = setInterval(function() < // сколько времени прошло с начала анимации? let timePassed = Date.now() - start; if (timePassed >= 2000) < clearInterval(timer); // закончить анимацию через 2 секунды return; >// отрисовать анимацию на момент timePassed, прошедший с начала анимации draw(timePassed); >, 20); // в то время как timePassed идёт от 0 до 2000 // left изменяет значение от 0px до 400px function draw(timePassed) < train.style.left = timePassed / 5 + 'px'; >

Для просмотра примера, кликните на него:

    #train      

Использование requestAnimationFrame

Теперь давайте представим, что у нас есть несколько анимаций, работающих одновременно.

Если мы запустим их независимо с помощью setInterval(. 20) , тогда браузеру будет необходимо выполнять отрисовку гораздо чаще, чем раз в 20ms .

Это происходит из-за того, что каждая анимация имеет своё собственное время старта и «каждые 20 миллисекунд» для разных анимаций – разные. Интервалы не выравнены и у нас будет несколько независимых срабатываний в течение 20ms .

setInterval(function() < animate1(); animate2(); animate3(); >, 20)

…Меньше нагружают систему, чем три независимых функции:

setInterval(animate1, 20); // независимые анимации setInterval(animate2, 20); // в разных местах кода setInterval(animate3, 20);

Эти независимые перерисовки лучше сгруппировать вместе, тогда они будут легче для браузера, а значит – не грузить процессор и более плавно выглядеть.

Существует ещё одна вещь, про которую надо помнить: когда CPU перегружен или есть другие причины делать перерисовку реже (например, когда вкладка браузера скрыта), нам не следует делать её каждые 20ms .

Но как нам узнать об этом в JavaScript? Спецификация Animation timing описывает функцию requestAnimationFrame , которая решает все описанные проблемы и делает даже больше.

let requestId = requestAnimationFrame(callback)

Такой вызов планирует запуск функции callback на ближайшее время, когда браузер сочтёт возможным осуществить анимацию.

Если в callback происходит изменение элемента, тогда оно будет сгруппировано с другими requestAnimationFrame и CSS-анимациями. Таким образом браузер выполнит один геометрический пересчёт и отрисовку, вместо нескольких.

Значение requestId может быть использовано для отмены анимации:

// отмена запланированного запуска callback cancelAnimationFrame(requestId);

Функция callback имеет один аргумент – время прошедшее с момента начала загрузки страницы в миллисекундах. Это значение может быть получено с помощью вызова performance.now().

Как правило, callback запускается очень скоро, если только не перегружен CPU или не разряжена батарея ноутбука, или у браузера нет какой-то ещё причины замедлиться.

Код ниже показывает время между первыми 10 запусками requestAnimationFrame . Обычно оно 10-20 мс:

  

Структура анимации

Теперь мы можем создать более сложную функцию анимации с помощью requestAnimationFrame :

function animate() < let start = performance.now(); requestAnimationFrame(function animate(time) < // timeFraction изменяется от 0 до 1 let timeFraction = (time - start) / duration; if (timeFraction >1) timeFraction = 1; // вычисление текущего состояния анимации let progress = timing(timeFraction); draw(progress); // отрисовать её if (timeFraction < 1) < requestAnimationFrame(animate); >>); >

Функция animate имеет три аргумента, которые описывают анимацию:

Продолжительность анимации. Например, 1000 .

Функция расчёта времени, как CSS-свойство transition-timing-function , которая будет вычислять прогресс анимации (как ось y у кривой Безье) в зависимости от прошедшего времени ( 0 в начале, 1 в конце).

Например, линейная функция значит, что анимация идёт с одной и той же скоростью:

function linear(timeFraction)

Это как если бы в transition-timing-function передать значение linear . Ниже будут представлены более интересные примеры.

Функция отрисовки, которая получает аргументом значение прогресса анимации и отрисовывает его. Значение progress=0 означает, что анимация находится в начале, и значение progress=1 – в конце.

Эта та функция, которая на самом деле и рисует анимацию.

Вот как она могла бы двигать элемент:

function draw(progress)

…Или делать что-нибудь ещё. Мы можем анимировать что угодно, как захотим.

Теперь давайте используем нашу функцию, чтобы анимировать свойство width от 0 до 100% .

Нажмите на элемент для того, чтобы посмотреть пример:

function animate() < let start = performance.now(); requestAnimationFrame(function animate(time) < let timeFraction = (time - start) / duration; if (timeFraction >1) timeFraction = 1; let progress = timing(timeFraction) draw(progress); if (timeFraction < 1) < requestAnimationFrame(animate); >>); >
     progress  elem.onclick = function() < animate(< duration: 1000, timing: function(timeFraction) < return timeFraction; >, draw: function(progress) < elem.style.width = progress * 100 + '%'; >>); >;  
animate(< duration: 1000, timing(timeFraction) < return timeFraction; >, draw(progress) < elem.style.width = progress * 100 + '%'; >>);

В отличие от CSS-анимаций, можно создать любую функцию расчёта времени и любую функцию отрисовки. Функция расчёта времени не будет ограничена только кривой Безье, а функция draw может менять не только свойства, но и создавать новые элементы (например, для создания анимации фейерверка).

Функции расчёта времени

Мы уже рассмотрели самый простой пример линейной функции расчёта времени выше.

Давайте посмотрим другие. Мы попробуем выполнить анимации с разными функциями расчёта времени, чтобы посмотреть как они работают.

Степень n

Если мы хотим ускорить анимацию, мы можем возвести progress в степень n .

Например, параболическая кривая:

function quad(timeFraction)

Если раньше анимационный эффект, такой как отскоки, был в начале, то после трансформации он будет показан в конце.

На графике выше красным цветом обозначена обычная функция и синим – после easeOut .

  • Обычный скачок – объект сначала медленно скачет внизу, а затем резко подпрыгивает вверх.
  • Обратный easeOut – объект вначале прыгает вверх, и затем скачет там.

easeInOut

Мы можем применить эффект дважды – в начале и конце анимации. Такая трансформация называется «easeInOut».

Для функции расчёта времени, анимация будет вычисляться следующим образом:

if (timeFraction else < // вторая половина анимации return (2 - timing(2 * (1 - timeFraction))) / 2; >
function makeEaseInOut(timing) < return function(timeFraction) < if (timeFraction < .5) return timing(2 * timeFraction) / 2; else return (2 - timing(2 * (1 - timeFraction))) / 2; >> bounceEaseInOut = makeEaseInOut(bounce);

В действии, bounceEaseInOut :

#brick < width: 40px; height: 20px; background: #EE6B47; position: relative; cursor: pointer; >#path
        

Функция «easeInOut» объединяет два графика в один: easeIn (обычный) для первой половины анимации и easeOut (обратный) – для второй половины.

Разница хорошо заметна, если сравнивать графики easeIn , easeOut и easeInOut для функции circ :

  • Красный обычный вариант circ ( easeIn ).
  • Зелёный – easeOut .
  • Синий – easeInOut .

Как видно, график первой половины анимации представляет собой уменьшенный easeIn , а второй – уменьшенный easeOut . В результате, анимация начинается и заканчивается одинаковым эффектом.

Более интересная функция «draw»

Вместо передвижения элемента мы можем делать что-нибудь ещё. Всё, что нам нужно – это правильно написать функцию draw .

Вот пример «скачущей» анимации набирающегося текста:

textarea < display: block; border: 1px solid #BBB; color: #444; font-size: 110%; >button
           

Итого

JavaScript может помочь в тех случаях, когда CSS не справляется или нужен жёсткий контроль над анимацией. JavaScript-анимации должны быть сделаны с помощью requestAnimationFrame . Это встроенный метод браузера, который вызывает переданную в него функцию в тот момент, когда браузер готовится совершить перерисовку (обычно это происходит быстро, но конкретные задержки зависят от браузера).

Когда вкладка скрыта, на ней совсем не происходит перерисовок, и функция не будет вызвана: анимация будет приостановлена и не потратит ресурсы. Это хорошо.

Вспомогательная функция animate для создания анимации:

function animate() < let start = performance.now(); requestAnimationFrame(function animate(time) < // timeFraction изменяется от 0 до 1 let timeFraction = (time - start) / duration; if (timeFraction >1) timeFraction = 1; // вычисление текущего состояния анимации let progress = timing(timeFraction); draw(progress); // отрисовать её if (timeFraction < 1) < requestAnimationFrame(animate); >>); >
  • duration – общая продолжительность анимации в миллисекундах.
  • timing – функция вычисления прогресса анимации. Получается момент времени от 0 до 1, возвращает прогресс анимации, обычно тоже от 0 до 1.
  • draw – функция отрисовки анимации.

Конечно, мы могли бы улучшить вспомогательную функцию и добавить в неё больше наворотов. Но JavaScript-анимации не каждый день используются, а только когда хотят сделать что-то интересное и необычное. Не стоит усложнять функцию до тех пор пока это вам не понадобились.

JavaScript-анимации могут использовать любые функции расчёта времени. Мы рассмотрели множество примеров и их вариаций, чтобы сделать их ещё более универсальными. В отличие от CSS, мы здесь не ограничены только кривой Безье.

То же самое и с draw : мы можем анимировать всё что угодно, не только CSS-свойства.

Создание анимации на базе JavaScript с помощью библиотеки Anime.js. Часть 1

С помощью Anime.js можно анимировать свойства CSS, SVG-изображения или атрибуты DOM-дерева на веб-странице. Позволяет контролировать все аспекты анимации.

Anime.js — небольшая библиотека для создания анимации на основе JavaScript. С её помощью можно анимировать свойства CSS, SVG-изображения или атрибуты DOM-дерева на веб-странице. Библиотека позволяет контролировать все аспекты анимации и предоставляет много способов для обозначения элементов, которые нужно привести в движение.

Вы полностью контролируете последовательность воспроизведения анимации и управляете синхронизацией анимации разных элементов друг относительно друга. Библиотека поддерживает все современные браузеры, включая IE10 и новее.

В этой серии обучающих статей вы узнаете обо всех функциях Anime.js и сможете применять библиотеку в своих проектах.

Примечание Если вы совсем новичок в JavaScript, предлагаем вам ознакомиться с вводной статьёй по этому языку программирования.

Установка библиотеки

Для установки можно использовать команды npm или bower :

npm install animejs bower install animejs 

Вы также можете загрузить библиотеку и включить в свой проект или ссылаться на её последнюю версию через CDN.

После успешной установки вы сможете использовать Anime.js для добавления интересных анимаций к вашим элементам. Давайте начнём с базовых возможностей библиотеки.

Определение целевых элементов

Для создания анимации с помощью Anime.js нужно вызвать функцию anime() и передать ей объект с парами ключ-значение, которые определяют целевые элементы и свойства, которые вы хотите анимировать. Вы можете использовать ключевое слово targets , чтобы дать библиотеке понять, что вам нужно анимировать. Это ключевое слово может принимать значение в разных форматах.

CSS-селекторы: вы можете передавать один или более селекторов в виде значений для ключевого слова targets .

var blue = anime(< targets: '.blue', translateY: 200 >); var redBlue = anime(< targets: '.red, .blue', translateY: 200 >); var even = anime(< targets: '.square:nth-child(even)', translateY: 200 >); var notRed = anime(< targets: '.square:not(.red)', translateY: 200 >); 

В первом случае Anime.js будет анимировать все элементы с классом blue . Во втором — blue или red . В третьем случае Anime.js будет анимировать все дочерние чётные элементы с классом square . А в последнем случае библиотека будет взаимодействовать со всеми элементами с классом square , у которых нет класса red .

See the Pen Setting Target as a CSS Selector by Monty (@Shokeen) on CodePen.

DOM-узлы (DOM node) или коллекция узлов (NodeList): вы можете также использовать DOM-узел или NodeList в качестве значения для ключевого слова targets . Посмотрите на пример использования DOM-узла для targets .

var special = anime(< targets: document.getElementById('special'), translateY: 200 >); var blue = anime(< targets: document.querySelector('.blue'), translateY: 200 >); var redBlue = anime(< targets: document.querySelectorAll('.red, .blue'), translateY: 200 >); var even = anime(< targets: document.querySelectorAll('.square:nth-child(even)'), translateY: 200 >); var notRed = anime(< targets: document.querySelectorAll('.square:not(.red)'), translateY: 200 >); 

В первом случае использовалась функция getElementById() , чтобы обратиться к определённому элементу. Функция querySelector() использовалась для обращения к элементу с классом blue . А функция querySelectorAll() применялась для обращения ко всем элементам внутри документа, которые соответствуют группе определённых селекторов или же, наоборот, не входят в неё.

Существует множество функций, которые вы также можете использовать для выбора целевого элемента. Например, вы можете обратиться к элементам с определённым классом, используя функцию getElementsByClassName() . Или к элементам с определённым тегом, используя функцию getElementsByTagName() .

Любая функция, возвращающая DOM-узел или NodeList, может использоваться для установки значения targets в Anime.js.

See the Pen Setting Target as a DOM Node or Node List by Monty (@Shokeen) on CodePen.

Объект: вы можете использовать объекты JavaScript в качестве значения для targets . Ключ этого объекта используется в качестве идентификатора, а значение — в качестве числа, которое нужно анимировать.

Затем вы сможете показать анимацию внутри другого HTML-элемента с помощью дополнительного JavaScript-кода. Ниже приведён пример анимации значений двух разных ключей одного объекта.

var filesScanned = < count: 0, infected: 0 >; var scanning = anime( < targets: filesScanned, count: 1000, infected: 8, round: 1, update: function() < var scanCount = document.querySelector('.scan-count'); scanCount.innerHTML = filesScanned.count; var infectedCount = document.querySelector('.infected-count'); infectedCount.innerHTML = filesScanned.infected; >>); 

Код выше будет приводить в движение счётчик сканированных файлов от 0 до 1 000 и счётчик заражённых файлов от 0 до 8. Помните, что вы можете анимировать числовые значения только таким образом. При попытке анимировать ключ из AAA в BOY будет выведено сообщение об ошибке.

Кроме того, в коде использовалась функция обратного вызова ключа update , который вызывается на каждый кадр во время выполнения анимации. Здесь она использовалась для обновления количества сканированных и заражённых файлов. Однако вы можете пойти дальше и показать пользователям сообщение об ошибке, когда количество заражённых файлов превысит определённый порог.

See the Pen Setting Target as an Object by Monty (@Shokeen) on CodePen.

Массив: возможность указывать массив JavaScript в качестве значения targets будет полезна, если вам нужно анимировать множество элементов, которые относятся к разным категориям. Например, если вы хотите анимировать DOM-узел, объект и множество других элементов, основанных на CSS-селекторах, то можно это сделать, поместив их в массив, а затем определить массив в качестве значения для targets . Пример ниже должен прояснить ситуацию.

var multipleAnimations = anime(< targets: [document.querySelectorAll('.blue'), '.red, #special'], translateY: 250 >); 

See the Pen Setting Target as an Array by Monty (@Shokeen) on CodePen.

Какие свойства можно анимировать с помощью Anime.js

Теперь вы знаете, как определить разные элементы, которые нужно анимировать. Пришло время узнать, какие свойства и атрибуты могут быть анимированы при использовании библиотеки.

Свойства CSS

К таким, например, относятся ширина, высота и цвет для разных целевых элементов. Финальные значения разных анимируемых свойств вроде background-color определяются с использованием lowerCamelCase. Таким образом background-color превращается в backgroundColor . Код ниже иллюстрирует анимацию положения объекта left и цвета фона ( backgroundColor ) целевого объекта.

var animateLeft = anime(< targets: '.square', left: '50%' >); var animateBackground = anime(< targets: '.square', backgroundColor: '#f96' >); 

See the Pen Animating CSS Properties in Anime.js by Monty (@Shokeen) on CodePen.

Свойства могут принимать разные виды значений, которые они бы приняли при использовании обычного CSS. Например, свойство left может иметь такие значения: 50vh , 500px или 25em . Вы также можете не указывать единицу измерения после числа, но в таком случае ею станет px по умолчанию. Аналогичные действия можно выполнить с background-color , указав цвет в виде шестнадцатеричного значения или при помощи кода RGB или HSL.

CSS-трансформирование

Преобразование по осям X и Y достигается с помощью свойств translateX и translateY . Аналогичным образом можно масштабировать, наклонять или вращать элемент вдоль определённой оси, используя свойства: scale (масштабирование), skew (наклон) или rotate (поворот), соответствующие этой конкретной оси.

Существует возможность определения разных углов или в градусах, или с помощью свойства turn . Значение turn, равное 1, соответствует 360 градусам. Это позволяет сделать вычисления проще, так как вы знаете, на сколько нужно повернуть элементы относительно своей оси. В примере ниже показано, как происходит анимация масштабирования, перехода или поворота как единичного свойства, так и всех сразу.

var animateScaling = anime(< targets: '.square', scale: 0.8 >); var animateTranslation = anime(< targets: '.square', translateX: window.innerWidth*0.8 >); var animateRotation = anime(< targets: '.square', rotate: '1turn' >); var animateAll = anime(< targets: '.square', scale: 0.8, translateX: window.innerWidth*0.8, rotate: '1turn' >); 

See the Pen Animating CSS Transforms in Anime.js by Monty (@Shokeen) on CodePen.

Атрибуты SVG

Единственное условие заключается в том, что значение атрибутов должно быть числовым. Способность анимировать разные атрибуты открывает возможности для создания некоторых классных эффектов. Поскольку эта статья ознакомительная, в ней будут приведены простые примеры.

По мере углубления в библиотеку вы будете узнавать, как создаются более сложные анимации. Ниже представлен код для анимации атрибутов круга cy , cx и stroke-width . Как и с другими свойствами CSS, для stroke-width надо использовать CamelCase, чтобы код работал корректно.

var animateX = anime(< targets: '.circle', cx: window.innerWidth*0.6 >); var animateStrokeWidth = anime(< targets: '.circle', strokeWidth: '25' >); 

See the Pen Animating SVG Attributes in Anime.js by Monty (@Shokeen) on CodePen.

Атрибуты DOM

Можно анимировать числовые атрибуты DOM, подобно тому, как вы анимировали атрибуты SVG. Это может быть полезным для работы с элементом progress в HTML5. У него есть два атрибута: value и max . В примере ниже будет выполняться анимация атрибута value , чтобы продемонстрировать прогресс перемещения файла на жёсткий диск.

var animateProgress = anime(< targets: 'progress', value: 100, easing: 'linear' >); 

See the Pen Animating DOM Attributes in Anime.js by Monty (@Shokeen) on CodePen.

Заключение

Вы познакомились со всеми вариантами выбора элементов в Anime.js, а также узнали, как анимировать разные свойства CSS и атрибуты, связанные с ними.

В следующей статье вы узнаете, как контролировать плавность, задержку и длительность анимации как для единичных свойств, так и для группы. Затем вы научитесь контролировать все эти параметры для каждого отдельного элемента.

Простые анимации

Вероятно, самым большим ограничением является то, что когда фигура нарисована, её уже нельзя двигать. Чтобы изобразить движение нам нужно перерисовать фигуру и всё, что было нарисовано до неё. Перерисовка сложных кадров занимает много времени, и производительность сильно зависит от скорости компьютера, на котором она выполняется.

Основные шаги анимации

Ниже перечислены необходимые шаги для того, чтобы нарисовать кадр:

  1. Очистить canvas Если фигура, которую вы собираетесь нарисовать, не занимает всю площадь canvas (как фон, например), то всё что было нарисовано ранее необходимо стереть. Проще всего это сделать при помощи метода clearRect() .
  2. Сохранить изначальное состояние canvas Если вы изменяете любые настройки (такие как стили, трансформации и т.п.), которые затрагивают состояние canvas и вы хотите убедиться, что оригинальное состояние используется каждый раз, когда был отрисован кадр, то вам следует сохранить это оригинальное состояние.
  3. Нарисовать анимированные фигуры Шаг на котором вы собственно отрисовываете кадр.
  4. Восстановить состояние canvas Если вы сохраняли состояние, восстановите его, прежде чем отрисовывать новый кадр.

Управление анимацией

Фигуры отрисовываются на canvas либо напрямую — при помощи методов canvas, либо с помощью сторонних функций. В нормальной ситуации результат станет виден на canvas после окончания выполнения скрипта. К примеру, цикл for использовать для анимации нельзя.

Это значит, нужен способ выполнения функций отрисовки через интервалы времени. Есть два способа для управления такой анимацией.

Запланированные обновления

Первый — это функции window.setInterval() (en-US), window.setTimeout() (en-US), и window.requestAnimationFrame() , которые могут быть использованы для вызова некоторой функции, через заданный промежуток времени.

Начинает периодически исполнять функцию function каждые delay миллисекунд.

Запускает выполнение указанной функции function через delay миллисекунд.

Сообщает браузеру, что вы хотите выполнить анимацию, и запрашивает, чтобы браузер вызвал указанную функцию callback для обновления анимации перед следующей перерисовкой.

Если вы не планируете никакого взаимодействия с пользователем, вы можете использовать функцию setInterval() , которая многократно выполняет, предоставленный ей код. Если же вы планируете создать игру, в которой контроль анимации осуществляется мышью или клавиатурой, то необходимо использовать setTimeout() . Установив EventListener (en-US), вы можете перехватываете любые действия пользователя и запустить соответствующие функции анимации.

Примечание: В примерах ниже мы будем использовать функцию window.requestAnimationFrame() для контроля анимации. Функция requestAnimationFrame является более эффективной для создания анимации, так как новая итерация вызывается, когда система готова к отрисовке нового кадра. Количество вызовов в секунду примерно равно 60 и уменьшается, когда вкладка неактивна. Для более подробного изучения цикла анимации, особенно для игр, прочитайте статью Анатомия видеоигр В Зоне разработке игр.

Анимированная солнечная система

В этом примере анимируется небольшая модель солнечной системы.

var sun = new Image(); var moon = new Image(); var earth = new Image(); function init()  sun.src = "canvas_sun.png"; moon.src = "canvas_moon.png"; earth.src = "canvas_earth.png"; window.requestAnimationFrame(draw); > function draw()  var ctx = document.getElementById("canvas").getContext("2d"); ctx.globalCompositeOperation = "destination-over"; ctx.clearRect(0, 0, 300, 300); // clear canvas ctx.fillStyle = "rgba(0,0,0,0.4)"; ctx.strokeStyle = "rgba(0,153,255,0.4)"; ctx.save(); ctx.translate(150, 150); // Earth var time = new Date(); ctx.rotate( ((2 * Math.PI) / 60) * time.getSeconds() + ((2 * Math.PI) / 60000) * time.getMilliseconds(), ); ctx.translate(105, 0); ctx.fillRect(0, -12, 50, 24); // Shadow ctx.drawImage(earth, -12, -12); // Moon ctx.save(); ctx.rotate( ((2 * Math.PI) / 6) * time.getSeconds() + ((2 * Math.PI) / 6000) * time.getMilliseconds(), ); ctx.translate(0, 28.5); ctx.drawImage(moon, -3.5, -3.5); ctx.restore(); ctx.restore(); ctx.beginPath(); ctx.arc(150, 150, 105, 0, Math.PI * 2, false); // Earth orbit ctx.stroke(); ctx.drawImage(sun, 0, 0, 300, 300); window.requestAnimationFrame(draw); > init(); 
canvas id="canvas" width="300" height="300">canvas> 

Анимированные часы

В этом примере создаются анимированные часы, показывающие правильное время.

function clock()  var now = new Date(); var ctx = document.getElementById("canvas").getContext("2d"); ctx.save(); ctx.clearRect(0, 0, 150, 150); ctx.translate(75, 75); ctx.scale(0.4, 0.4); ctx.rotate(-Math.PI / 2); ctx.strokeStyle = "black"; ctx.fillStyle = "white"; ctx.lineWidth = 8; ctx.lineCap = "round"; // Hour marks ctx.save(); for (var i = 0; i  12; i++)  ctx.beginPath(); ctx.rotate(Math.PI / 6); ctx.moveTo(100, 0); ctx.lineTo(120, 0); ctx.stroke(); > ctx.restore(); // Minute marks ctx.save(); ctx.lineWidth = 5; for (i = 0; i  60; i++)  if (i % 5 != 0)  ctx.beginPath(); ctx.moveTo(117, 0); ctx.lineTo(120, 0); ctx.stroke(); > ctx.rotate(Math.PI / 30); > ctx.restore(); var sec = now.getSeconds(); var min = now.getMinutes(); var hr = now.getHours(); hr = hr >= 12 ? hr - 12 : hr; ctx.fillStyle = "black"; // write Hours ctx.save(); ctx.rotate( hr * (Math.PI / 6) + (Math.PI / 360) * min + (Math.PI / 21600) * sec, ); ctx.lineWidth = 14; ctx.beginPath(); ctx.moveTo(-20, 0); ctx.lineTo(80, 0); ctx.stroke(); ctx.restore(); // write Minutes ctx.save(); ctx.rotate((Math.PI / 30) * min + (Math.PI / 1800) * sec); ctx.lineWidth = 10; ctx.beginPath(); ctx.moveTo(-28, 0); ctx.lineTo(112, 0); ctx.stroke(); ctx.restore(); // Write seconds ctx.save(); ctx.rotate((sec * Math.PI) / 30); ctx.strokeStyle = "#D40000"; ctx.fillStyle = "#D40000"; ctx.lineWidth = 6; ctx.beginPath(); ctx.moveTo(-30, 0); ctx.lineTo(83, 0); ctx.stroke(); ctx.beginPath(); ctx.arc(0, 0, 10, 0, Math.PI * 2, true); ctx.fill(); ctx.beginPath(); ctx.arc(95, 0, 10, 0, Math.PI * 2, true); ctx.stroke(); ctx.fillStyle = "rgba(0,0,0,0)"; ctx.arc(0, 0, 3, 0, Math.PI * 2, true); ctx.fill(); ctx.restore(); ctx.beginPath(); ctx.lineWidth = 14; ctx.strokeStyle = "#325FA2"; ctx.arc(0, 0, 142, 0, Math.PI * 2, true); ctx.stroke(); ctx.restore(); window.requestAnimationFrame(clock); > window.requestAnimationFrame(clock); 
canvas id="canvas" width="150" height="150">canvas> 

Зацикленная панорама

В этом примере панорама прокручивается слева направо. Мы используем фото национального парка Йосемити взятое из Википедии, но вы можете использовать любое изображение, большее элемента canvas.

var img = new Image(); // User Variables - customize these to change the image being scrolled, its // direction, and the speed. img.src = "capitan_meadows,_yosemite_national_park.jpg"; var CanvasXSize = 800; var CanvasYSize = 200; var speed = 30; //lower is faster var scale = 1.05; var y = -4.5; //vertical offset // Main program var dx = 0.75; var imgW; var imgH; var x = 0; var clearX; var clearY; var ctx; img.onload = function ()  imgW = img.width * scale; imgH = img.height * scale; if (imgW > CanvasXSize)  x = CanvasXSize - imgW; > // image larger than canvas if (imgW > CanvasXSize)  clearX = imgW; > // image larger than canvas else  clearX = CanvasXSize; > if (imgH > CanvasYSize)  clearY = imgH; > // image larger than canvas else  clearY = CanvasYSize; > //Get Canvas Element ctx = document.getElementById("canvas").getContext("2d"); //Set Refresh Rate return setInterval(draw, speed); >; function draw()  //Clear Canvas ctx.clearRect(0, 0, clearX, clearY); //If image is if (imgW  CanvasXSize)  //reset, start from beginning if (x > CanvasXSize)  x = 0; > //draw aditional image if (x > CanvasXSize - imgW)  ctx.drawImage(img, x - CanvasXSize + 1, y, imgW, imgH); > > //If image is > Canvas Size else  //reset, start from beginning if (x > CanvasXSize)  x = CanvasXSize - imgW; > //draw aditional image if (x > CanvasXSize - imgW)  ctx.drawImage(img, x - imgW + 1, y, imgW, imgH); > > //draw image ctx.drawImage(img, x, y, imgW, imgH); //amount to move x += dx; > 

Заметьте, что ширина и высота должны совпадать со значениями CanvasXZSize и CanvasYSize .

canvas id="canvas" width="800" height="200">canvas> 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *