目前的網頁都右側邊欄,有的是在左側,類似於導航欄,如一些購物商城,還有一些是在網頁的右下角,一般是提示客服信息和微信/QQ等服務。
這里都涉及到一個動畫效果的展示,即點擊側邊欄時會在側邊欄的右側或者左側出現相應的信息。如下圖慕課網右下角的側邊欄,把鼠標放在最后一個微信圖標上,會彈出慕課網的二維碼。
實現動畫效果的方式有兩種,一種是JavaScript setInterval函數,即設置定時器,實現簡單,但是效果不佳。動畫效果不夠平滑,而且實現的效果有限,不能實現旋轉和3D變換。用戶體驗有待提高。另一種是使用CSS3來實現動畫效果。
css屬性
描述動畫的運行屬性(運行時間、次數等)
transition (過渡)
animations( 動畫)
描述動畫的執行屬性(參與動畫的屬性,效果等)
transform (變形)——translate
代碼實現:
sidebar.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>sideBar demo</title> <link rel="stylesheet" href="css/style.css"> <link rel="stylesheet" href="bootstrap/dist/css/bootstrap.css"> <link rel="stylesheet" href="bootstrap/dist/css/bootstrap-theme.css"> </head> <body> <div id = "sidebar"> <ul> <li id="prof" class="item"> <span class="glyphicon glyphicon-user"></span> <div>我</div> </li> <li id="asset" class="item"> <span class="glyphicon glyphicon-user"></span> <div>資產</div> </li> <li id="brand" class="item"> <span class="glyphicon glyphicon-user"></span> <div>商品</div> </li> <li id="foot" class="item"> <span class="glyphicon glyphicon-user"></span> <div>足跡</div> </li> <li id="calender" class="item"> <span class="glyphicon glyphicon-user"></span> <div>日歷</div> </li> </ul> <div id="closeBar"> <span class="glyphicon glyphicon-remove"></span> </div> </div> <div class="nav-content" id="prof-content"> <div class="nav-con-close"> <span class="glyphicon glyphicon-chevron-left"></span> </div> <div>我</div> </div> <div class="nav-content" id="asset-content"> <div class="nav-con-close"> <span class="glyphicon glyphicon-chevron-left"></span> </div> <div>資產</div> </div> <div class="nav-content" id="brand-content"> <div class="nav-con-close"> <span class="glyphicon glyphicon-chevron-left"></span> </div> <div>商標</div> </div> <div class="nav-content" id="foot-content"> <div class="nav-con-close"> <span class="glyphicon glyphicon-chevron-left"></span> </div> <div>足跡</div> </div> <div class="nav-content" id="calender-content"> <div class="nav-con-close"> <span class="glyphicon glyphicon-chevron-left"></span> </div> <div>日歷</div> </div> <script src="sideBar.js"></script> </body> </html>
注:
<!--頁面加載順序是單線程的,加載頁面時是從上到下加載,如果在上面遇到script標簽或者css時,頁面的
渲染就會停止,服務器就回去下載.js和.css文件代碼,下載后運行,我們會看到頁面停頓,這是種非常不好的體驗
所以目前的做法都是把<script>標簽放在</body>上面-->
<!--完好體驗的頁面順序安排
1、先下載css樣式
2、渲染HTML文檔結構
3、再下載JavaScript代碼-->
style.css
ul{ list-style: none; padding-left: 0; } #sidebar{ width: 35px; background-color: #e1e1e1; padding-top: 200px; /*設置高度100%都是相對父元素的100%,fixed使該元素脫離流,相對屏幕的100%,即全屏*/ position: fixed; min-height:100%; z-index: 100; } .item{ font-size: 12px; font-family: 'Microsoft New Tai Lue'; text-align: center; margin-top: 5px; } #closeBar{ position: absolute; bottom: 30px; width: 35px; text-align: center; /*提示別人是個按鈕 手的樣式*/ cursor: pointer; } .nav-content{ width: 200px; position: fixed; min-height: 100%; background-color: #e1e1e1; /*調試代碼時經常使用border,幫我們定位到div的一個區域*/ border: 1px solid black; z-index: 99; /*使用透明度為0來隱藏元素*/ opacity: 0; } .nav-con-close{ position: absolute; top: 5px; right: 5px; cursor: pointer; } .sidebar-move-left{ -webkit-animation:sml; -o-animation:sml; animation:sml; /*持續時間*/ -webkit-animation-duration: 1s; -moz-animation-duration: 1s; -o-animation-duration: 1s; animation-duration: 1s; -webkit-animation-iteration-count: 1; -moz-animation-iteration-count: 1; -o-animation-iteration-count: 1; animation-iteration-count: 1; /*執行方向,動畫執行結束時保持在它結束時的狀態*/ animation-fill-mode: forwards; -moz-animation-fill-mode: forwards; -o-animation-fill-mode: forwards; -webkit-animation-fill-mode: forwards; } @keyframes sml { from{ } to{ transform: translateX(-120px); } } .closebar-move-right{ -webkit-animation:cmr; -o-animation:cmr; animation:cmr; /*持續時間*/ -webkit-animation-duration: 1s; -moz-animation-duration: 1s; -o-animation-duration: 1s; animation-duration: 1s; -webkit-animation-iteration-count: 1; -moz-animation-iteration-count: 1; -o-animation-iteration-count: 1; animation-iteration-count: 1; /*執行方向,動畫執行結束時保持在它結束時的狀態*/ animation-fill-mode: forwards; -moz-animation-fill-mode: forwards; -o-animation-fill-mode: forwards; -webkit-animation-fill-mode: forwards; } @keyframes cmr { from{ } to{ transform: translateX(160px) rotate(405deg) scale(1.5); } } .sidebar-move-right{ -webkit-animation:smr; -o-animation:smr; animation:smr; /*持續時間*/ -webkit-animation-duration: 1s; -moz-animation-duration: 1s; -o-animation-duration: 1s; animation-duration: 1s; -webkit-animation-iteration-count: 1; -moz-animation-iteration-count: 1; -o-animation-iteration-count: 1; animation-iteration-count: 1; /*執行方向,動畫執行結束時保持在它結束時的狀態*/ animation-fill-mode: forwards; -moz-animation-fill-mode: forwards; -o-animation-fill-mode: forwards; -webkit-animation-fill-mode: forwards; } @keyframes smr { from{ } to{ transform: translateX(120px); } } .closebar-move-left{ -webkit-animation:cml; -moz-animation-name: cml; -o-animation:cml; animation:cml; /*持續時間*/ -webkit-animation-duration: 1s; -moz-animation-duration: 1s; -o-animation-duration: 1s; animation-duration: 1s; -webkit-animation-iteration-count: 1; -moz-animation-iteration-count: 1; -o-animation-iteration-count: 1; animation-iteration-count: 1; /*執行方向,動畫執行結束時保持在它結束時的狀態*/ animation-fill-mode: forwards; -moz-animation-fill-mode: forwards; -o-animation-fill-mode: forwards; -webkit-animation-fill-mode: forwards; } @keyframes cml { from{ transform: scale(1.5); } to{ transform:translateX(-160px) rotate(-405deg) scale(1); } } .menuContent-move-right{ -webkit-animation:mmr; -moz-animation-name: mmr; -o-animation:mmr; animation:mmr; /*持續時間*/ -webkit-animation-duration: .5s; -moz-animation-duration: .5s; -o-animation-duration: .5s; animation-duration: .5s; -webkit-animation-iteration-count: 1; -moz-animation-iteration-count: 1; -o-animation-iteration-count: 1; animation-iteration-count: 1; /*執行方向,動畫執行結束時保持在它結束時的狀態*/ animation-fill-mode: forwards; -moz-animation-fill-mode: forwards; -o-animation-fill-mode: forwards; -webkit-animation-fill-mode: forwards; } @keyframes mmr { from{ opacity: 0; } to{ opacity: 1; transform:translateX(120px); } } .menuContent-move-left{ -webkit-animation:mml; -moz-animation-name: mml; -o-animation:mml; animation:mml; /*持續時間*/ -webkit-animation-duration: 1s; -moz-animation-duration: 1s; -o-animation-duration: 1s; animation-duration: 1s; -webkit-animation-iteration-count: 1; -moz-animation-iteration-count: 1; -o-animation-iteration-count: 1; animation-iteration-count: 1; /*執行方向,動畫執行結束時保持在它結束時的狀態*/ animation-fill-mode: forwards; -moz-animation-fill-mode: forwards; -o-animation-fill-mode: forwards; -webkit-animation-fill-mode: forwards; } @keyframes mml { from{ opacity: 1; } to{ opacity: 0; transform:translateX(-120px); } } .menuContent-move-up{ -webkit-animation:mmu; -moz-animation-name: mmu; -o-animation:mmu; animation:mmu; /*持續時間*/ -webkit-animation-duration: 1s; -moz-animation-duration: 1s; -o-animation-duration: 1s; animation-duration: 1s; -webkit-animation-iteration-count: 1; -moz-animation-iteration-count: 1; -o-animation-iteration-count: 1; animation-iteration-count: 1; /*執行方向,動畫執行結束時保持在它結束時的狀態*/ animation-fill-mode: forwards; -moz-animation-fill-mode: forwards; -o-animation-fill-mode: forwards; -webkit-animation-fill-mode: forwards; } @keyframes mmu { from{ opacity: 0; } to{ opacity: 1; transform:translateY(-250px); } }
sidebar.js
/* var sideBar = {} 會造成全局污染,sideBar賦給Windows,作為windows的一個屬性*/ /*目前常用模塊模式的方法,避免全局污染*/ /*立即執行函數*/ (function () { var MenuBar = function () { this.el = document.querySelector('#sidebar ul'); this.state = 'allClosed'; /*禁止向上傳播,不然點擊sidebar中的ul也會觸發和點擊關閉按鈕一樣的事件*/ this.el.addEventListener('click',function (e) { e.stopPropagation(); }); var self = this; this.menulist = document.querySelectorAll('#sidebar ul > li'); this.currentOpenMenuContent = null; for(var i = 0;i<this.menulist.length;i++){ this.menulist[i].addEventListener('click',function (e) { var menuContentEl = document.getElementById(e.currentTarget.id +'-content'); if(self.state === 'allClosed'){ console.log('open'+menuContentEl.id); menuContentEl.style.top = '0'; menuContentEl.style.left = '-85px'; menuContentEl.className = 'nav-content'; menuContentEl.classList.add('menuContent-move-right'); self.state='hasOpened'; self.currentOpenMenuContent = menuContentEl; }else{ console.log('closed'+self.currentOpenMenuContent.id); console.log('open'+menuContentEl.id); self.currentOpenMenuContent.className = 'nav-content'; self.currentOpenMenuContent.style.top = '0'; self.currentOpenMenuContent.style.left = '35px'; self.currentOpenMenuContent.classList.add('menuContent-move-left'); menuContentEl.className='nav-content'; menuContentEl.style.top = '250px'; menuContentEl.style.left = '35px'; menuContentEl.classList.add('menuContent-move-up'); self.state='hasOpened'; self.currentOpenMenuContent = menuContentEl; } }); } this.menuContentList = document.querySelectorAll('.nav-content > div.nav-con-close'); for(var i=0;i<this.menuContentList.length;i++){ this.menuContentList[i].addEventListener('click',function (e) { var menuContent = e.currentTarget.parentNode; menuContent.className = 'nav-content'; menuContent.style.top = '0'; menuContent.style.left ='35px'; menuContent.classList.add('menuContent-move-left'); this.state='allClosed'; }); } }; /*Sidebar第一個字母大寫,構造函數的基本規范 */ var Sidebar = function (eId,closeBarId) { this.state = 'opened'; this.el = document.getElementById(eId || 'sidebar'); this.closeBarEl = document.getElementById(closeBarId || 'closeBar'); /*默認向上冒泡,第三個參數可以不寫*/ var self = this; this.menubar = new MenuBar(); this.el.addEventListener('click',function (event) { if(event.target !== self.el){ //console.log(this); self.triggerSwich(); } }); } Sidebar.prototype.close = function () { console.log('關閉sidebar'); this.el.className = 'sidebar-move-left'; this.closeBarEl.className = 'closebar-move-right'; this.state = 'closed'; }; Sidebar.prototype.open = function () { console.log('打開sidebar'); this.el.style.left = '-120px'; this.el.className = 'sidebar-move-right'; this.closeBarEl.style.left = '160px'; this.closeBarEl.className = 'closebar-move-left'; this.state = 'opened'; }; Sidebar.prototype.triggerSwich = function () { if(this.state === 'opened'){ this.close(); }else{ this.open(); } }; var sidebar = new Sidebar(); })();