这是一款基于TweenMax的炫酷手机APP环形导航菜单设计效果。该环形菜单默认为一个汉堡包按钮,当用户点击按钮时,子菜单会一个接一个绕着汉堡包按钮出现,效果非常酷。
使用方法
HTML结构
该环形菜单特效的HTML代码非常简单,如下:
<div class="bg"></div> <div class="phone"> <div class="screen"> <h1 class="hello">Welcome!</h1> <div class="nav"> <a class="home" href="#"> <img class="open" src="img/menu.svg" title="Menu" width="30"> <img class="close" src="img/close.svg" title="Close" width="30"> </a> <a class="item profile" href="#"><img src="img/user.svg" alt="User" width="25"></a> <a class="item like" href="#"><img src="img/heart.svg" alt="Like" width="25"></a> <a class="item message" href="#"><img src="img/message.svg" alt="Message" width="25"></a> <a class="item tools" href="#"><img src="img/tools.svg" title="Tools" width="25"></a> </div><!-- .nav --> </div><!-- .screen --> </div><!-- .phone -->
CSS样式
.nav
元素是导航菜单,采用相对定位。它下面的每一个<a>
元素都是一个圆形按钮。尺寸为50像素。
.nav { position: relative; top: 12px; left: 12px; } .nav a { width: 50px; height: 50px; border-radius: 50%; text-align: center; display: block; box-sizing: border-box; background-color: #FFFFFF; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.14); } .nav a img { position: relative; top: 50%; transform: translateY(-50%); }
a.home
元素是主菜单按钮。它的尺寸为60像素,使用绝对定位,位于左上角位置。其它的子菜单按钮使用绝对定位分布在它的周围。
.nav a.home { width: 60px; height: 60px; position: absolute; left: 0px; top: 0px; z-index: 2; } .nav a.home img { position: relative; top: 50%; left: 50%; transform: translate(-50%, -50%); } .nav a.profile { position: absolute; left: 113px; top: -5px; } .nav a.like { position: absolute; left: 115px; top: 59px; } .nav a.message { position: absolute; left: 65px; top: 106px; } .nav a.tools { position: absolute; top: 114px; left: 0; }
主菜单按钮中有两张图片,分别为汉堡包图片和关闭按钮图片。在主菜单按钮被激活的时候,会被添加.active
class类,此时关闭按钮图片被隐藏,反之显示关闭按钮图片。
.home:not(.active) .close, .home.active .open { display: none; } .home.active .close, .home:not(.active) .open { display: block; }
JavaScript
特效中使用TweenMax来控制环形菜单的打开和关闭,为相应的元素添加和移除项的class类。
$(window).load(function() { var tl = new TimelineMax({ paused: true }), tlback = new TimelineMax({ paused: true }), intro = new TimelineMax(); intro .from('.phone', 1, { autoAlpha: 0 }) .from('.hello', 0.5, { autoAlpha: 0 }, 0.5) tl .to('.hello', 0.3, { autoAlpha: 0 }) .set('.home', { className: '+=active' }) .set('.item', { scale: 1 }) // fix for a bug when on of the item was appearing at 0.5 scale .to('.home', 0.1, { scale: 1.2, yoyo: true, repeat: 1 }) .to('.home', 0.3, { x: 20, y: 20, ease: Elastic.easeOut.config(1, 0.5) }, 0) .staggerFrom('.item', 0.7, { left: 20, top: 20, autoAlpha: 0, scale: 0.5, ease: Elastic.easeOut.config(1, 0.5) }, 0.1); tlback .set('.home', { className: '-=active' }) .staggerTo('.item', 0.7, { left: 20, top: 20, autoAlpha: 0, scale: 0.5, ease: Elastic.easeOut.config(1, 0.5) }, 0.1) .to('.hello', 0.3, { autoAlpha: 1 }) .to('.home', 0.3, { x: 0, y: 0, ease: Power2.easeOut }, 0.5); $(document).on('click', '.home:not(.active)', function(e) { event.preventDefault(); tl.play(0); }); $(document).on('click', '.home.active, .item', function(e) { event.preventDefault(); TweenMax.to($(this), 0.1, { scale: 1.2, yoyo: true, repeat: 1, onComplete: function() { tlback.play(0) } }); }); });