Организация простой анимации на javascript

Анимация и другие эффекты на JavaScript

Приветствую вас дорогие друзья! В этом уроке я покажу, как можно реализовать анимацию на javascript без использования готовых библиотек!

В данном уроке будет затронута простая анимация – плавное изменение ширины и высоты объекта.

Также, будут представлены 2 примера (с картинкой и с блоком), которые вы сможете скачать к себе на компьютер.

 

Реализация

Напишем функцию, которая будет принимать 4 параметра:

  1. текущий элемент;
  2. свойство (высоту или ширину);
  3. новое значение свойства;
  4. время в секундах.

С объектом можно будет проделать следующее:

  • увеличить ширину:
  • уменьшить ширину;
  • увеличить высоту;
  • уменьшить высоту.

 

Код функции на javascript:

<script type="text/javascript"> window.free = true; function myAnimation(el,prop,val,time){ window.cur_prop; eval(‘window.cur_prop = el.style.’ + prop); cur_prop = cur_prop.substring(0,cur_prop.length-2); if( val > cur_prop){ time = time * 1000 / ( val — cur_prop ); }else{ time = time * 1000 / ( cur_prop — val ); } if(free){ free = false; function calc() { if( val > cur_prop){ cur_prop++; eval("el.style." + prop + "=’" + cur_prop + "px’"); }else{ if( val < cur_prop){ cur_prop—; eval("el.style." + prop + "=’" + cur_prop + "px’"); } } } setInterval(calc, time); } } </script>

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

Изначально free равно истине (true), когда мы нажимаем на объект (исполняем функцию) мы меняем значение переменное на ложь (false).

Далее идет переменная cur_prop, в нем мы храним текущее значение ширины или высоты объекта (с помощью style берем значение и обрезаем 2 символа с конца “px”), для которого применяется анимация.

Далее необходимо вычислить время (скорость), которое будет использоваться в интервале.

Если переданное значение ширины или высоты больше текущего (то есть необходимо увеличить), то вычисляем по формуле:

время = время умножить на 1000 и разделить на ( переданное значение — текущее значение ), то есть, если нужно изменить ширину объекта, например, со 100 до 600 пикселей за 10 секунд, то после вычисления получим, что размеры буду увеличиваться со скоростью 1 пиксель каждые 20 миллисекунд: время = 10 секунд * 1000 / ( 600px — 100px ) = 20 (миллисекунд) если необходимо уменьшать, то применяем эту же формулу, но вычитаем уже из текущего значения.

Далее проверяем переменную free – если она равна истине (то есть на объект еще ни разу не нажали), то запускаем интервал setInterval, который будет выполнять функцию calc каждые 20 миллисекунд (если следовать примеру выше).

Функция calc выполняем увеличение или уменьшение объекта с помощью изменения его css правила (высоты или ширины).

Сначала проверяем, что будем делать – увеличивать или уменьшать объект, и, в зависимости от этого, будем прибавлять единицу к текущему значению, либо уменьшать на единицу.

Когда переданное и текущее свойства совпадут (например, текущая высота станет равной переданной), то изменения закончатся (закончится анимация).

Теперь давайте рассмотрим 2 простых примера, каждый из которых вы можете скачать к себе на компьютер.

 

Первый пример

В данном примере будет показано изменение ширины картинки с 300px до 500px за 5 секунд.

HTML код картинки:

<img style="width:300px;height:200px;" onclick="myAnimation(this,’width’,500,5)" src="http://sergey-oganesyan.ru/wp-content/uploads/2017/03/img.jpg">

 

Второй пример

Во втором примере показано изменение высоты блока с 200px до 500px за 10 секунд

HTML код блока:

<div style="width:300px;height:200px;background:green" onclick="myAnimation(this,’height’,500,10)"></div>

 

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

На этом все, желаю вам удачи, пока!

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

Анимация спрайтов

Последнее обновление: 14.11.2015

Нередко для отрисовки спрайтов используются целые спрайт-листы, которые представляют набор изображений в рамках одного спрайта. Плавное перемещение подобных изображений рождает иллюзию движения.

Анимация на чистом javascript

Например, у нас есть следующий спрайт:

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

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

Определим следующий код игры:

using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; namespace Game1 { public class Game1 : Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D texture; Vector2 position = Vector2.Zero; int frameWidth = 108; int frameHeight = 140; Point currentFrame = new Point(0, 0); Point spriteSize = new Point(8, 2); public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = «Content»; TargetElapsedTime = new System.TimeSpan(0, 0, 0, 0, 400); } protected override void Initialize() { base.Initialize(); } protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); texture = Content.Load<Texture2D>(«scottpilgrim_multiple»); } protected override void UnloadContent() { } protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit(); ++currentFrame.X; if (currentFrame.X >= spriteSize.X) { currentFrame.X = 0; ++currentFrame.Y; if (currentFrame.Y >= spriteSize.Y) currentFrame.Y = 0; } base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend); spriteBatch.Draw(texture, position, new Rectangle(currentFrame.X * frameWidth, currentFrame.Y * frameHeight, frameWidth, frameHeight), Color.White, 0, Vector2.Zero, 1, SpriteEffects.None, 0); spriteBatch.End(); base.Draw(gameTime); } } }

Ключевыми для отрисовки нужного фрейма из спрайта являются следующие переменные:

int frameWidth = 108; int frameHeight = 140; Point currentFrame = new Point(0, 0); Point spriteSize = new Point(8, 2);

Переменные и указывают соответственно на ширину и высоту фрейма, то есть отдельного изображения на спрайте. Переменная currentFrame, представляющая структуру Point, задает положение текущего фрейма. По умолчанию мы устанавливаем значение , то есть самый первый фрейм на спрайте. Размер спрайта задается через переменную . Ее значение указывает, что на спрайте 8 фреймов по ширине и 2 фрейма по высоте.

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

++currentFrame.X; if (currentFrame.X >= spriteSize.X) { currentFrame.X = 0; ++currentFrame.Y; if (currentFrame.Y >= spriteSize.Y) currentFrame.Y = 0; }

После этого происходит отрисовка спрайта с помощью перегрузки метода :

spriteBatch.Draw(texture, position, new Rectangle(currentFrame.X * frameWidth, currentFrame.Y * frameHeight, frameWidth, frameHeight), Color.White, 0, Vector2.Zero, 1, SpriteEffects.None, 0);

При запуске приложения начнется анимация фреймов в спрайт-листов. Однако мы можем столкнуться, что анимация работает слишком быстро. В этом случае мы можем установить явным образом частоту смены кадров. Для этого добавим в конструктор класса Game1 следующую строку:

TargetElapsedTime = new System.TimeSpan(0, 0, 0, 0, 50);

Свойство TargetElapsedTime задает частоту смены кадров. В данном случае в качестве времени игрового цикла устанавливается 50 миллисекунд. То есть кадры будут меняться с частотой в 1000 / 50 = 20 раз в секунду, что меньше стандартного значения (60 раз в секунду).

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

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

Поэтому удалим из конструктора строку:

TargetElapsedTime = new System.TimeSpan(0, 0, 0, 0, 50);

И добавим в класс Game1 две глобальные переменные:

int currentTime = 0; // сколько времени прошло int period = 50; // период обновления в миллисекундах

И после этого изменим метод Update:

protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit(); // добавляем к текущему времени прошедшее время currentTime += gameTime.ElapsedGameTime.Milliseconds; // если текущее время превышает период обновления спрайта if (currentTime > period) { currentTime -= period; // вычитаем из текущего времени период обновления ++currentFrame.X; // переходим к следующему фрейму в спрайте if (currentFrame.X >= spriteSize.X) { currentFrame.X = 0; ++currentFrame.Y; if (currentFrame.Y >= spriteSize.Y) currentFrame.Y = 0; } } base.Update(gameTime); }

С помощью свойства gameTime.ElapsedGameTime.Milliseconds мы можем получить время игрового цикла, по умолчанию это примерно 1000/60 = 16 миллисекунд.

И затем это время добавляем переменной currentTime, которое содержит время, прошедшее после последнего обновления фреймов. Если это время окажется больше интервала обновления фреймов, то переходим к новому фрейму.

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

using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; namespace Game1 { public class Game1 : Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D texture; Vector2 position = Vector2.Zero; float speed = 5f; int currentTime = 0; // сколько времени прошло int period = 50; // частота обновления в миллисекундах int frameWidth = 108; int frameHeight = 140; Point currentFrame = new Point(0, 0); Point spriteSize = new Point(8, 2); public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = «Content»; } protected override void Initialize() { base.Initialize(); } protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); texture = Content.Load<Texture2D>(«scottpilgrim_multiple»); } protected override void UnloadContent() { } protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit(); currentTime += gameTime.ElapsedGameTime.Milliseconds; if (currentTime > period) { currentTime -= period; position.X += speed; if (position.X > Window.ClientBounds.Width — frameWidth || position.X < 0) { speed *= -1; ++currentFrame.Y; if (currentFrame.Y >= spriteSize.Y) currentFrame.Y = 0; } ++currentFrame.X; if (currentFrame.X >= spriteSize.X) { currentFrame.X = 0; } } base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend); spriteBatch.Draw(texture, position, new Rectangle(currentFrame.X * frameWidth, currentFrame.Y * frameHeight, frameWidth, frameHeight), Color.White, 0, Vector2.Zero, 1, SpriteEffects.None, 0); spriteBatch.End(); base.Draw(gameTime); } } }

НазадСодержаниеВперед

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

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

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

В то же время мы были вдохновлены работой Тома Чиоволони и игрой «The Floor is Jelly», поэтому мы специально начали с реализации желеобразной физики.

Результат вылился в библиотеку, которую мы назвали jelly.js, в которую мы добавили все, что нужно, чтобы получить желеобразую форму. Давайте посмотрим, как ее использовать!

Создание фигур с помощью SVG

Мы решили создавать фигуры с помощью SVG, потому что это самый простой способ: мы можем создавать нужные нам формы в векторном редакторе (например, Inkscape или Illustrator) и вставлять их непосредственно в наш HTML-документ или даже импортировать их из JavaScript. Создадим вот такую простую форму в векторном редакторе:

Затем включим соответствующий SVG-код непосредственно в HTML:

Настройка HTML разметки

Нам также потребуется canvas, чтобы нарисовать фигуру и другие элементы с целью перемещения буквы «S» относительно средней точки формы.

Немного CSS

Для этого примера нам нужно совсем CSS стилей:

Давайте сделаем желе

Наконец, мы подошли к самой интересной части! Давайте нарисуем наш пятиугольник на canvas и анимируем его. Не беспокойтесь, — это будет очень просто с помощью нашей библиотеки.

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

Обратите внимание, что конструктор нашей библиотеки (jelly.js) получает элемент canvas и набор опций. Мы также можем предоставить массив опций или набор параметров для каждой фигуры, которую мы хотим рисовать. Подробное описание доступных опций вы можете проверить на Github репозитории.

Можно было бы оставить так и ничего не менять, но у нашей библиотеки еще есть огромный потенциал. Итак, давайте посмотрим, что мы еще можем сделать.

Внедрение желеобразного перетаскивания

Чтобы проиллюстрировать немного больше возможностей, которые у нас есть (и для удовольствия), давайте посмотрим, как мы можем поколебать наш пятиугольник, когда мы перетаскиваем его по экрану. Для этого нам нужно знать, когда указатель мыши находится внутри формы, чтобы перетащить ее только в этом случае. Взгляните на следующий код:

Давайте посмотрим, как мы можем реализовать базовую логику перетаскивания. Пожалуйста, ознакомьтесь с комментариями, чтобы разобраться в происходящем и обратите особое внимание на функцию shake:

Производительность и поддержка браузерами

Все современные браузеры поддерживают canvas, но jelly.js использует промисы, поэтому вам потребуется полиполк для браузеров, которые не поддерживает промисы.

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

Заключение

Мы создали поистине желеобразный пятиугольник без особых усилий.

Between.js — создаем анимацию в стиле Cocoa Animation

Наша форма также изменяет курсор при наведении и реагирует на перетаскивание! Результат вы можете увидеть здесь или скачать и протестировать локально.

Это не единственное, что мы можем сделать. Во второй части нашего урока мы построим удивительный слайдер, где все будет одно сплошное желе.

В общих чертах мы узнаем, как:

  • Нарисовать больше желе-форм и текст!
  • Использовать изображения внутри фигур, а не только сплошные цвета.
  • Анимировать фигуры, чтобы показать их или плавно скрыть.
  • Менять форму желе.
  • Сделать весь слайдер адаптивным.

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

Закрыть меню