需求
一些Mobile版本的网站,上面顶部菜单图标,按上去可以展开菜单,再点击,可以收回菜单,如图所示:
下面分享我项目中用到的菜单Toggle效果的代码
实现
利用CSS画出三个横线,以及一个叉叉,然后加入动画效果
<!doctype html> <html> <head> <style> .menu-toggle .span { height: 2px; margin: 7px 0 0 0; transition: all .3s ease-out; backface-visibility: visible; visibility: visible; opacity: 1; } .menu-toggle { position: absolute; right: 10px; top: 10px; z-index: 999; width: 24px; height: 24px; cursor: pointer; float: right; transition: all .3s ease-out; } .menu-toggle .span { border-radius: 5px; background: #0478cf; transition: all 0.3s ease-out; backface-visibility: hidden; } .menu-toggle .top.span.active { transform: rotate(45deg) translateX(3px) translateY(5px); } .menu-toggle .middle.span.active { opacity: 0; } .menu-toggle .bottom.span.active { transform: rotate(-45deg) translateX(8px) translateY(-10px); } </style> </head> <body> <div id="app"> <div class="menu-toggle" @click="menuToggled()"> <div class="span top" :class="{ active: isMenuActive }"></div> <div class="span middle" :class="{ active: isMenuActive }"></div> <div class="span bottom" :class="{ active: isMenuActive }"></div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <script> var app = new Vue({ el: '#app', data: { isMenuActive: false, }, created() { }, methods: { menuToggled: function () { this.isMenuActive = !this.isMenuActive; }, } }) </script> </body> </html>
另一种写法:
<!doctype html> <html> <head> <style> .frame { position: absolute; top: 50%; left: 50%; width: 400px; height: 400px; margin-top: -200px; margin-left: -200px; border-radius: 2px; box-shadow: 1px 2px 10px 0px rgba(0, 0, 0, 0.3); background: #3FAF82; color: #fff; } .center { position: absolute; top: 50%; left: 50%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); } .menu-icon { width: 80px; height: 52px; cursor: pointer; z-index: 50; } .menu-icon .line-1, .menu-icon .line-2, .menu-icon .line-3 { height: 8px; width: 100%; background-color: #fff; border-radius: 3px; box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.3); transition: background-color .2s ease-in-out; } .menu-icon .line-1 { -webkit-animation: animate-line-1-rev .7s ease-in-out; animation: animate-line-1-rev .7s ease-in-out; } .menu-icon .line-2 { margin: 14px 0; -webkit-animation: animate-line-2-rev .7s ease-in-out; animation: animate-line-2-rev .7s ease-in-out; } .menu-icon .line-3 { -webkit-animation: animate-line-3-rev .7s ease-in-out; animation: animate-line-3-rev .7s ease-in-out; } .menu-icon:hover .line-1, .menu-icon:hover .line-2, .menu-icon:hover .line-3 { background-color: #fff; } .menu-icon.active .line-1, .menu-icon.active .line-2, .menu-icon.active .line-3 { background-color: #fff; } .menu-icon.active .line-1 { -webkit-animation: animate-line-1 0.7s cubic-bezier(0.3, 1, 0.7, 1) forwards; animation: animate-line-1 0.7s cubic-bezier(0.3, 1, 0.7, 1) forwards; } .menu-icon.active .line-2 { -webkit-animation: animate-line-2 0.7s cubic-bezier(0.3, 1, 0.7, 1) forwards; animation: animate-line-2 0.7s cubic-bezier(0.3, 1, 0.7, 1) forwards; } .menu-icon.active .line-3 { -webkit-animation: animate-line-3 0.7s cubic-bezier(0.3, 1, 0.7, 1) forwards; animation: animate-line-3 0.7s cubic-bezier(0.3, 1, 0.7, 1) forwards; } .no-animation { -webkit-animation: none !important; animation: none !important; } @-webkit-keyframes animate-line-1 { 0% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } 50% { -webkit-transform: translate3d(0, 22px, 0) rotate(0); transform: translate3d(0, 22px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, 22px, 0) rotate(45deg); transform: translate3d(0, 22px, 0) rotate(45deg); } } @keyframes animate-line-1 { 0% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } 50% { -webkit-transform: translate3d(0, 22px, 0) rotate(0); transform: translate3d(0, 22px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, 22px, 0) rotate(45deg); transform: translate3d(0, 22px, 0) rotate(45deg); } } @-webkit-keyframes animate-line-2 { 0% { -webkit-transform: scale(1); transform: scale(1); opacity: 1; } 100% { -webkit-transform: scale(0); transform: scale(0); opacity: 0; } } @keyframes animate-line-2 { 0% { -webkit-transform: scale(1); transform: scale(1); opacity: 1; } 100% { -webkit-transform: scale(0); transform: scale(0); opacity: 0; } } @-webkit-keyframes animate-line-3 { 0% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } 50% { -webkit-transform: translate3d(0, -22px, 0) rotate(0); transform: translate3d(0, -22px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, -22px, 0) rotate(135deg); transform: translate3d(0, -22px, 0) rotate(135deg); } } @keyframes animate-line-3 { 0% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } 50% { -webkit-transform: translate3d(0, -22px, 0) rotate(0); transform: translate3d(0, -22px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, -22px, 0) rotate(135deg); transform: translate3d(0, -22px, 0) rotate(135deg); } } @-webkit-keyframes animate-line-1-rev { 0% { -webkit-transform: translate3d(0, 22px, 0) rotate(45deg); transform: translate3d(0, 22px, 0) rotate(45deg); } 50% { -webkit-transform: translate3d(0, 22px, 0) rotate(0); transform: translate3d(0, 22px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } } @keyframes animate-line-1-rev { 0% { -webkit-transform: translate3d(0, 22px, 0) rotate(45deg); transform: translate3d(0, 22px, 0) rotate(45deg); } 50% { -webkit-transform: translate3d(0, 22px, 0) rotate(0); transform: translate3d(0, 22px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } } @-webkit-keyframes animate-line-2-rev { 0% { -webkit-transform: scale(0); transform: scale(0); opacity: 0; } 100% { -webkit-transform: scale(1); transform: scale(1); opacity: 1; } } @keyframes animate-line-2-rev { 0% { -webkit-transform: scale(0); transform: scale(0); opacity: 0; } 100% { -webkit-transform: scale(1); transform: scale(1); opacity: 1; } } @-webkit-keyframes animate-line-3-rev { 0% { -webkit-transform: translate3d(0, -22px, 0) rotate(135deg); transform: translate3d(0, -22px, 0) rotate(135deg); } 50% { -webkit-transform: translate3d(0, -22px, 0) rotate(0); transform: translate3d(0, -22px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } } @keyframes animate-line-3-rev { 0% { -webkit-transform: translate3d(0, -22px, 0) rotate(135deg); transform: translate3d(0, -22px, 0) rotate(135deg); } 50% { -webkit-transform: translate3d(0, -22px, 0) rotate(0); transform: translate3d(0, -22px, 0) rotate(0); } 100% { -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } } </style> </head> <body> <div id="app"> <div class="frame"> <div class="center"> <div class="menu-icon" :class="{active: isMenuActive}" @click="menuToggled"> <div class="line-1"></div> <div class="line-2"></div> <div class="line-3"></div> </div> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <script> var app = new Vue({ el: '#app', data: { isMenuActive: true, }, created() { console.log("created") }, methods: { menuToggled: function() { this.isMenuActive = !this.isMenuActive; console.log(this.isMenuActive); }, } }) </script> </body> </html>
文章评论