Як створити плавно змінюється кнопку Play-Pause для HTML5 відео з допомогою SVG

18

Від автора: якщо уважно придивитися до плеєра YouTube, можна помітити, що кнопка play не просто переключається на іконку паузи по кліку, а плавно і швидко перетікає між двома станами. Зробити це можна з допомогою SVG під управлінням JavaScript. Сьогодні я покажу мою інтерпретацію даного UI шаблону.

Створюємо цільові стану для плавного переходу

Основна умова виконання плавного переходу з одного стану в інший в SVG – кількість вершин в обох станах повинне збігатися. Також в SVG можна розбити замкнуте елемент і перетворити його в два. Тобто у випадку з кнопкою play в SVG нам доведеться ховати деякі вершини стану паузи (8 або більше вершин) в самій кнопці (для якої потрібно всього 3 вершини). Також це означає, що кнопка play має складатися з двох окремих частин, але виглядати як одне ціле.

Я створив трикутник в Adobe Illustrator на аркуші розміром 50 х 50 пікселів. Прив’язавши трикутник до шару, поверх нього я створив два окремих елемента, що повторюють його форму.

Два елементи накладаються один на одного в середині. Зверніть увагу, що правий трикутник складається з 5 точок, а не 4, щоб зберегти форму стрілки. Найбільші праві три вершини мають свою позицію, але можуть перекривати один одного. Після експорту в SVG і зачистки коду розмітка виглядає наступним чином:

Play

Кожен polygon потрібно анімувати в новий стан. Перетягнувши існуючі точки і перетворивши іконку в два вертикальних прямокутника, результат можна експортувати і додати в попередній SVG значень тегів animate. SVG тепер став таким:

Play

У попередній статті по SVG морфизму я вас вже познайомив з двома новими атрибутами з цього коду. Атрибут begin=»indefinite» забороняє швидкий старт анімації (для тіста можете просто видалити цей атрибут). Атрибут fill=»freeze» – те ж саме, що animation-direction: forward в CSS (анімація відтворюється один раз і застигає у кінцевому стані). Також теги animate я розташував після полігонів, а не всередині них, а посилання на анимируемые елементи поставив за допомогою xlink:href.

Після переходу SVG стан паузи необхідно повернути його назад в режим play. На жаль, в SVG немає простої інверсії рухів, нам доведеться створити друге цільове стан:

Play

Кожній анімації я присвоїв свій ID (id: lefttopause і lefttoplay).

Розставляємо всі на місця

Для спрощеного доступу SVG поміщений в тег button:

Play

Налаштування включають в себе приховування SVG за замовчуванням. З’являтися кнопка буде за допомогою JS:

* { box-sizing: border-box; }
#atlanticlight {
position: relative;
font-size: 0; width: 100%;
}
#atlanticlight, #atlanticlight video, #atlanticlight button {
width: 100%; height: auto;
}
#atlanticlight button svg {
width: 50%; margin: 0 auto;
fill: #fff; padding: 3rem;
transition: .6s opacity;
}
#atlanticlight video, #atlanticlight button {
position: absolute; top: 0;
}
#atlanticlight button {
background: transparent;
outline: none; border: none;
cursor: pointer;
}
#playpause { display: none; }
.playing { opacity: 0; }

Властивість transition на тезі svg, застосоване через клас, змусить кнопку плавно з’являтися і зникати. Додавати і видаляти клас ми будемо через classList.

Наводимо все в рух

Щоб кнопка play/pause запрацювала, необхідно визначити елементи, з якими ми будемо працювати:

var atlanticlight = document.querySelector(«#atlanticlight video»),
playpause = document.getElementById(«playpause»),
lefttoplay = document.getElementById(«lefttoplay»),
righttoplay = document.getElementById(«righttoplay»),
lefttopause = document.getElementById(«lefttopause»),
righttopause = document.getElementById(«righttopause»);

Застосовуючи техніку прогресивного поліпшення, ми видаляємо стандартні кнопки з відео і показуємо наш власний UI:

mountain.removeAttribute(«контроль»);
vidcontrols.style.display = «block»;

Тепер необхідно ловити подія кліку на кнопку button. Ми не будемо відслідковувати стан елемента, ми будемо дивитися на стан відео:

atlanticlight.removeAttribute(«контроль»);
playpause.style.display = «block»;
playpause.addEventListener. (‘click’,function(){
if (atlanticlight.paused) {
atlanticlight.play();
playpause.classList.add(«playing»);
lefttopause.beginElement();
righttopause.beginElement();
} else {
atlanticlight.pause();
lefttoplay.beginElement();
righttoplay.beginElement();
playpause.classList.remove(«playing»);
}
},false);

Майбутні напрацювання

Якщо відкрити консоль Chrome і запустити приклад вище, ви отримаєте наступне повідомлення: «SVG SMIL анімація (animate, set і т. д.) застаріла і буде видалена. Будь ласка, скористайтесь CSS або веб-анімацією.»

На щастя чи ні, це правда: незабаром Chrome повністю відмовиться від SMIL (мову на основі SVG, який ми досі використовували для анімації) на догоду Web Animations API. На жаль, у новій специфікації поки що нічого не сказано про морфизм, що ставить цей код у скрутне становище на досить довгий проміжок часу. Наш код буде в підвішеному стані, поки не буде розроблена окрема JS бібліотека, або поки Web Animations API не розшириться. На цей перехідний період ми можемо використовувати бібліотеку анімації Greensock як фолбэка, більш докладно про неї я розповім в наступній статті.