Ознайомлення з вражаючими можливостями SVG-анімацій: пишемо невелику гру [*]


Дізнайтесь більше про нові кар'єрні можливості в EchoUA. Цікаві проекти, ринкова оплата, гарний колектив. Надсилайте резюме та приєднуйтеся до нас.

Розповідає Грег Хованесян


Ідея гри

Я вже давно ознайомлений з SVG-анімаціями і добре розумію, як можна їх використати для створення анімованого спрайту або дизайну веб-сторінок. Таке поєднання, як GreenSock і нативний CSS, працювало чудово. Тому я подумав і вирішив піти далі – створити за їх допомогою невелику гру. Зрозуміло, з тим, що відмінно працювало, анімованим дизайном. Отже, одного разу вночі до мене прийшла ідея гри, я зробив начерки і показав їх братові – професійному дизайнерові. Ми обговорили всі деталі, і я приступив до роботи.

Як грати: Стрибаючий м’яч змінює колір. Ми повинні стежити за його кольором і змінювати колір колон, на які він падає, щоб кольори збігалися. Одне натиснення на колону робить її червоною, два – жовтою, три – фіолетовою.

Процес створення

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

Це не керівництво, тому я детально не пояснюватиму кожен рядок коду. Але я покажу Вам декілька класних прийомів, а Ви зможете погратися з кодом на CodePen. Крім того, я поділюся з Вами декількома корисними матеріалами. Код також супроводжується коментарями.

GSAP – це дуже потужний інструмент, тому недивно, що я ним користувався. Крім того, у CodePen є вбудований компілятор Babel, я можу писати там ES6-код, у якого є багато можливостей: синтаксис класів, стрілочні функції тощо. Детальніше про це можна дізнатися тут.

Я також припускаю, що Ви вже знайомі з GSAP, але якщо ні, то ось відмінний курс для вивчення.

Фонова анімація

Все, що Ви бачите на фоні – це SVG. Кожна хвиля, кожен шар гір і хмари – це окремі div ‘и. Не складно було б створити фон лише одним SVG і анімувати дочірні елементи – Greensock це може, достатньо задати їм ID. Справа в тому, що тоді анімація не працюватиме на мобільних пристроях.

var wave1 = TweenMax.to ('.wave1', 0.7, {backgroundPositionX: '-=54px', repeat: - 1, ease: Power0.easeNone});

Тут ми використовуємо інструмент TweenMax для зрушення фону на 54 пікселі з постійною швидкістю. Те саме ми робимо і з горами і хмарами. Задаючи кожному елементу унікальну швидкість, ми отримуємо непоганий ефект паралакса.

Зверніть увагу, що скрізь парять маленькі частки. Я генерую їх випадковим чином і анімую циклічним:

{rotation: 360, transformOrigin: "-"+radius+"px -"+radius+" px", ...}

Вони всі повільно обертаються, і це виглядає трохи хаотично.

Анімація колон

У кожній колоні є маленькі елементи, що рухаються. Їх я створив просто засобами HTML/CSS. SCSS заощадив величезну кількість часу і рядків коду. Я створив окремі міксини для кожної фігури всередині колони. Подивіться на ефект для бульбашок. Кожне коло має абсолютне позиціонування, а його стиль задається міксином. Створення трикутників у CSS займає ще більше рядків коду, тому міксини виглядають ще вигідніше.

Подивіться на червону колону з бульбашками.

@mixin bubble ($size, $top, $left) { height: $size; width: $size; top: $top; left: $left;}
@mixin bubble_hollow ($size, $top, $left) { @include bubble ($size, $top, $left); background-color: transparent; border-style: solid;}

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

.bubble - 4 { @include bubble (15px, 98px, 37px);}.bubble - 5 { @include bubble_hollow (5px, 116px, 20px);}

Анімація бульбашок

Для такого ефекту я використав відкладені анімації. Вони зачіпають усі елементи всередині колони, але рухатися вони розпочинають з невеликою затримкою. Більше про цей прийом можна прочитати тут.

Анімація трикутників

У жовтій колоні я додав ефект перевороту. Зверніть увагу, що деякі з елементів обертаються навколо вертикальної осі, а деякі – навколо горизональної. Тут я використовую властивість cycle:

var triangle = new TimelineMax ({delay: 0.5});triangle .staggerTo (el.find ('.triangle'), 1.5, { cycle:{ rotationY: [0, 360], rotationX: [360, 0], }, repeat: - 1, repeatDelay: 0.1 }, 0.1);

Анімація блоків

Те саме я використовую і в третій колоні: частина елементів рухається ліворуч, частина – праворуч.

Анімація вікна з результатами

Натисніть Rerun, щоб відтворити анімацію.

Я хотів використати для цього вікна ефект желе, і він зайняв лише декілька рядків:

var resultTimeline = new TimelineMax ();resultTimeline .fromTo ('.stop - game .score - container', 0.7, { opacity: 0, scale: 0.3 }, { opacity: 1, scale: 1, ease: Elastic.easeOut.config (1.25, 0.5)}) .fromTo ('.stop - game .final - score', 2, { scale: 0.5 }, { scale: 1, ease: Elastic.easeOut.config (2, 0.5)}, 0) .fromTo ('.stop - game .result', 1, { scale: 0.5 }, { scale: 1, ease: Elastic.easeOut.config (1.5, 0.5)}, 0.3) ;

Для створення такого еластичного ефекту треба лише задати відповідну плавність. Щоб вибрати відповідну плавність, Ви можете скористатися цим інструментом: виберіть Elastic і визначтеся з параметрами.

Flexbox

Звичайно ж, я використав Flexbox (до речі, зовсім нещодавно його за умовчанням став підтримувати Bootstrap.) Для тих, хто не ознайомлеий з ним, відмінна ввідна стаття. Щойно Ви почнете використовувати Flexbox, то вже не зможете жити без нього. Отже, подивимось на екран головного меню і самої гри.

Контейнер “Start Game” задається наступним кодом:

{ display: flex; flex-direction: column; justify-content: space - between; align-items: center;}

flex-direction: column задає напрям, в якому елементи розташовуються в контейнері. Значення за умовчанням (row) розмістив би їх в ряд зліва направо. Потім йде justify - content. Він розподіляє вільне місце, і ми можемо вибрати, чи хочемо ми додати проміжки ліворуч, праворуч або взагалі навколо всього елемента. Ми встановлюємо значення space - between, що підіймає “Top” вгору, “How to Play” розміщує внизу, а “Logo Holder” – в центрі (весь вільний простір розташований між цими елементами). align-items: center центрує елементи відносно горизонтальної осі.

“How to Play” – це гнучкий елемент:

{ display: flex; width: 100%;}

Ми не задаємо напрям, тому три секції розміщуються в один ряд. У секцій 1 і 3 параметр ” flex” встановлений в 1, тому вони займають усе вільне місце. Звичайно, можна було використати justify-content: space - around у елементі “How to Play”, але я хотів, щоб секція 2 розташовувалася саме в центрі.

Це сцена гри, з властивістю display: flex. У ній є два контейнери. Я не хотів робити розташування м’яча абсолютним, намагався, щоб він був рівно над колонами, і прагнув придумати рішення на CSS, щоб воно працювало, навіть якщо я поміняю висоту колон. Тому властивість flex-direction-контейнера дорівнює column, і це саме те, що треба. justify-content: space - between піднімає контейнер з м’ячем вгору, а контейнер з колонами закріплює внизу. Тепер застосуємо до верхнього контейнера наступні властивості:

{ display: flex; flex-direction: column; justify-content: flex - end;}

Він теж стає гнучким, ми робимо вертикальну вісь головною і потім рухаємо вміст до кінця контейнера за допомогою justify-content: flex - end, тому м’яч опускається вниз.

Уявіть собі реалізацію всього цього без Flexbox

Робимо гру масштабованою

Ось що було по-справжньому складно. Подивіться, як добре гра виглядає на екранах з різним дозволом. Для цього я просто використав CSS-трансформації. Покладемо дозвіл за умовчанням, що дорівнює 1200x800px. Потім, якщо Ваш екран відрізняється за дозволом, контейнер гри треба відмасштабувати за допомогою коефіцієнта screenHeight / 800. Звичайно, треба враховувати і портретне розташування пристрою. Ось потрібний код:

var scale =  (screenWidth > screenHeight) ? screenHeight/800: screenWidth/1200;

Проте виглядає це поки що не дуже привабливо. Вікно є дуже маленьким.

Тому контейнер треба збільшити на такий самий коефіцієнт, щоб він займав увесь екран. Якщо ми збільшимо його вдвічі, то нам потрібно збільшити в два рази його початковий розмір, щоб отриманий розмір став займав увесь екран. А може, екран занадто великий, і нам треба зменшити розмір в 1,2 разу. Загалом, ось потрібний код:

$('.container') .css ('transform', 'scale (' + this.scale + ')') .css ('height', height/this.scale) .css ('width', width/this.scale) .css ('transformOrigin', 'left top');

Переклад статті “How to create a game using SVG animations (Coloron example) “

Київ, Харків, Одеса, Дніпро, Запоріжжя, Кривий Ріг, Вінниця, Херсон, Черкаси, Житомир, Хмельницький, Чернівці, Рівне, Івано-Франківськ, Кременчук, Тернопіль, Луцьк, Ужгород, Кам'янець-Подільський, Стрий - за статистикою саме з цих міст програмісти найбільше переїжджають працювати до Львова. А Ви розглядаєте relocate?


Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *