Перевод статьи на tympanus.net
Несколько примеров эластичных компонентов с анимацией SVG фигур для улучшения взаимодействия с пользователем.
Сегодня мы бы хотели продемонстрировать несколько примеров добавления эффекта эластичности. Идея заключается в внедрении SVG элемента в компонент страницы, с целью его дальнейшей анимации. Данную технику можно применить к меню, кнопкам или другим элементам пользовательского интерфейса.
Для анимации SVG, будем использовать Snap.svg. Это отличная JavaScript библиотека для работы с SVG.
В качестве иконок используем Font Awesome.
Для демонстрации элементов draggable & droppable мы используем Dragabilly от David DeSandro.
Помните, что данные примеры будут корректно работать только в последних версиях браузеров.
Ниже один из примеров использования SVG с компонентами (в нашем случае в меню):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<nav id="menu" class="menu"> <button class="menu__handle"><span>Menu</span></button> <div class="menu__inner"> <ul> <li><a href="#"><i class="fa fa-fw fa-home"></i><span>Home<span></a></li> <li><a href="#"><i class="fa fa-fw fa-heart"></i><span>Favs<span></a></li> <li><a href="#"><i class="fa fa-fw fa-folder"></i><span>Files<span></a></li> <li><a href="#"><i class="fa fa-fw fa-tachometer"></i><span>Stats<span></a></li> </ul> </div> <div class="morph-shape" data-morph-open="M300-10c0,0,295,164,295,410c0,232-295,410-295,410" data-morph-close="M300-10C300-10,5,154,5,400c0,232,295,410,295,410"> <svg width="100%" height="100%" viewBox="0 0 600 800" preserveAspectRatio="none"> <path fill="none" d="M300-10c0,0,0,164,0,410c0,232,0,410,0,410"/> </svg> </div> </nav> |
Мы используем два data
атрибута для хранения SVG путей, которые в дальнейшем будем видоизменять (в зависимости от того, открываем ли мы или закрываем меню).
Элементы SVG будут располагаться абсолютно по отношению к меню; так же нам нужно немного пространства для того, чтобы во время анимации элементы не обрезались. Помните, что при расширении SVG на 100%, пропорции не сохраняются. Это очень важно в случае использования некоторых фигур. В данном примере мы выставляем не только 100% высоте и ширине элемента, но и задаем фиксированные размеры для контейнера содержащего SVG:
1 2 3 4 5 6 7 8 9 10 11 12 |
.morph-shape { position: absolute; width: 240px; height: 100%; top: 0; right: 0; } .morph-shape svg path { stroke: #5f656f; stroke-width: 5px; } |
Используя Snap.svg
мы можем видоизменить форму объекта
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
(function() { function SVGMenu( el, options ) { this.el = el; this.init(); } SVGMenu.prototype.init = function() { this.trigger = this.el.querySelector( 'button.menu__handle' ); this.shapeEl = this.el.querySelector( 'div.morph-shape' ); var s = Snap( this.shapeEl.querySelector( 'svg' ) ); this.pathEl = s.select( 'path' ); this.paths = { reset : this.pathEl.attr( 'd' ), open : this.shapeEl.getAttribute( 'data-morph-open' ), close : this.shapeEl.getAttribute( 'data-morph-close' ) }; this.isOpen = false; this.initEvents(); }; SVGMenu.prototype.initEvents = function() { this.trigger.addEventListener( 'click', this.toggle.bind(this) ); }; SVGMenu.prototype.toggle = function() { var self = this; if( this.isOpen ) { classie.remove( self.el, 'menu--anim' ); setTimeout( function() { classie.remove( self.el, 'menu--open' ); }, 250 ); } else { classie.add( self.el, 'menu--anim' ); setTimeout( function() { classie.add( self.el, 'menu--open' ); }, 250 ); } this.pathEl.stop().animate( { 'path' : this.isOpen ? this.paths.close : this.paths.open }, 350, mina.easeout, function() { self.pathEl.stop().animate( { 'path' : self.paths.reset }, 800, mina.elastic ); } ); this.isOpen = !this.isOpen; }; new SVGMenu( document.getElementById( 'menu' ) ); })(); |
Надеемся, что данные примеры произвели на вас впечатление!