[1]頁面設計 [2]菜單邏輯 [3]功能實現 [4]完整源碼 ...
×
目錄
[1]頁面設計 [2]菜單邏輯 [3]功能實現[4]完整源碼前面的話
本文是DOM滑鼠事件的一個實際應用。查看博客園的博客文章時,有的文章非常長,卻沒有回到頂部按鈕;而且文章的點贊和評論都在文章最底部,使用時並不方便。所以使用自定義右鍵菜單來實現回到頂部、點贊、評論這三個主要功能
頁面設計
首先將這三個功能以一個列表<ul>的形式放置。滑鼠移入時樣式改變,移出時還原
<style> body{margin: 0;} ul{ margin: 0; padding: 0; list-style: none; } .list{ width: 100px; text-align: center; cursor: pointer; font:20px/40px '宋體'; background-color: #eee; } .in:hover{ background-color: lightblue; color: white; font-weight:bold; } </style> <ul id="list" class="list"> <li class="in">頂部</li> <li class="in">點贊</li> <li class="in">評論</li> </ul>
菜單邏輯
菜單邏輯共包括阻止預設行為、顯隱效果和位置判斷三個部分
預設行為
通常,點擊右鍵時,會彈出瀏覽器的預設右側菜單
通過return false可以實現阻止預設行為的效果,當然也可以使用preventDefault()和returnValue,詳細信息移步至此
document.oncontextmenu = function(){
return false;
}
顯隱
右鍵菜單預設隱藏,點擊右鍵時顯示,點擊左鍵時再隱藏
關於元素顯隱,個人總結過共9種思路,本文就用最簡單的display屬性
<div id="test" style="height: 100px;width: 100px;background-color: pink;"></div> <script> document.onclick = function(){ test.style.display = 'none'; } document.oncontextmenu = function(){ test.style.display = 'block'; return false; } </script>
位置判斷
滑鼠對象共有6對坐標位置信息,若把右鍵菜單設置為fixed固定定位,則選擇clientX/Y即可
一般地,右鍵菜單的左上角位置應該是當前滑鼠的坐標處
但是,還有另外2種情況需要考慮
【1】如果滑鼠的位置到視口底部的位置小於菜單的高度,則滑鼠的位置為菜單的底部位置
【2】如果滑鼠的位置到視口右側的位置小於菜單的寬度,則視口的右側為菜單的右側
元素的尺寸信息共有偏移尺寸offset、可視區尺寸client和滾動尺寸scroll,此時菜單的寬高應該為偏移尺寸offsetWidth/offsetHeight(全尺寸包含width、padding、border)
<div id="test" style="position:fixed;height: 100px;width: 100px;background-color: pink;"></div> <script> document.onclick = function(){ test.style.display = 'none'; } document.oncontextmenu = function(e){ e = e || event; test.style.left = e.clientX + 'px'; test.style.top = e.clientY + 'px'; //註意,由於加法、減法的優先順序高於大於、小於的優先順序,所以不用加括弧,詳細情況移步至此 if(document.documentElement.clientHeight - e.clientY < test.offsetHeight){ test.style.top = e.clientY - test.offsetHeight + 'px'; } if(document.documentElement.clientWidth - e.clientX < test.offsetWidth){ test.style.left = document.documentElement.clientWidth - test.offsetHeight + 'px'; } test.style.display = 'block'; return false; } </script>
功能實現
共用有回到頂部、點贊和評論三個功能需要實現
回到頂部
回到頂部共有5種實現方法,下麵使用可讀寫的scrollTop屬性進行效果實現
<body style="height: 3000px;"> <button id="test" style="position:fixed;right:10px;bottom:10px;">回到頂部</button> <script> var timer = null; test.onclick = function(){ cancelAnimationFrame(timer); timer = requestAnimationFrame(function fn(){ var oTop = document.body.scrollTop || document.documentElement.scrollTop; if(oTop > 0){ document.body.scrollTop = document.documentElement.scrollTop = oTop - 160; timer = requestAnimationFrame(fn); }else{ cancelAnimationFrame(timer); } }); } </script> </body>
點贊
點贊函數是博客園自己寫的,我們看不到內部函數也無法使用。如果想在右鍵菜單中使用點贊功能,就需要模擬點擊事件。點擊右鍵菜單中的點贊項時,觸發博客園的自帶的點贊項的click事件
由下圖可知,點贊函數加在<div class="diggit">上
由一個小例子來說明模擬點擊事件如何實現
點擊按鈕1時,顯示1;點擊按鈕2時,也要實現同樣的功能
<button id="btn1">按鈕1</button> <button id="btn2">按鈕2</button> <div id="result" style="height: 30px;width: 100px;background-color: pink;"></div> <script> btn1.onclick= function(){ result.innerHTML += '1'; } btn2.onclick = btn1.onclick; </script>
如法炮製
<div id="test">點贊</div> <script> window.onload = function(){ test.onclick = document.getElementById('div_digg').children[0].onclick; } </script>
增加獲取最新點贊數的功能
當id為'menuFavour'的div元素被點擊時,更新點贊數。但,由於從伺服器獲取最新數據以及相關元素的內容發生變化,都需要時間,所以增加2秒的延遲
<div id="menuFavour">點贊(<span id="favourNum">0</span>贊)</div> <script> //模擬原始點贊按鈕的點擊事件 menuFavour.onclick = document.getElementById('div_digg').children[0].onclick; //獲取贊成數的函數 function getfavourNum(){ favourNum.innerHTML = document.getElementById('digg_count').innerHTML; } //頁面載入時獲取贊成數 getfavourNum(); //點擊菜單中的贊成項後,再獲取最新的贊成數 menuFavour.addEventListener('click',function(){ setTimeout(function(){ getfavourNum(); },2000); }) </script>
評論
點擊右鍵菜單中的評論項時,頁面定位到評論區的位置
由圖中可知,評論區為<div id="comment_form_container">
將元素置於可視區域內有很多方法,如scrollTo()、scrollBy()、通過scrollTop計算、scrollIntoView()方法等等,詳細情況移步至此
下麵利用scrollIntoView()方法滾動當前元素,進入瀏覽器的可見區域
<div id="test">評論</div> <script> window.onload = function(){ test.onclick = function(){ document.getElementById('comment_form_container').scrollIntoView(); } } </script>
完整源碼
將HTML結構和CSS樣式寫成javascript生成的行為,最終形成一份js文件,代碼如下
<script> /*******生成元素*******/ var list = document.createElement('ul'); list.id = 'list'; list.innerHTML = '<li id="menuTop">回到頂部</li>\ <li id="menuFavour">點贊(<span id="favourNum">0</span>贊)</li>\ <li id="menuCommand">評論</li>'; document.body.appendChild(list); /*******添加樣式**********/ function loadStyles(str){ var style = document.createElement("style"); style.type = "text/css"; try{ style.innerHTML = str; }catch(ex){ style.styleSheet.cssText = str; } var head = document.getElementsByTagName('head')[0]; head.appendChild(style); } loadStyles("#list{margin: 0!important;\ padding: 0!important;\ width: 120px;\ text-align: center;\ cursor: pointer;\ font:20px/40px '宋體';\ background-color: #eee;\ position:fixed;\ display:none;}\ #list li{list-style:none!important;}\ #list li:hover{background-color: lightblue;color: white;font-weight:bold;}"); window.onload = function(){ /********顯示和隱藏菜單***********/ //左鍵點擊時,菜單隱藏 document.onclick = function(){ list.style.display = 'none'; } //右鍵點擊時,菜單顯示 document.oncontextmenu = function(e){ e = e || event; //通常情況下,菜單的位置就是滑鼠的位置 list.style.left = e.clientX + 'px'; list.style.top = e.clientY + 'px'; //當滑鼠的位置到視口底部的位置小於菜單的高度,則滑鼠的位置為菜單的底部位置 if(document.documentElement.clientHeight - e.clientY < list.offsetHeight){ list.style.top = e.clientY - list.offsetHeight + 'px'; } //當滑鼠的位置到視口右側的位置小於菜單的寬度,則視口的右側為菜單的右側 if(document.documentElement.clientWidth - e.clientX < list.offsetWidth){ list.style.left = document.documentElement.clientWidth - list.offsetHeight + 'px'; } list.style.display = 'block'; return false; } /*********回到頂部功能*********/ var timer = null; menuTop.onclick = function(){ cancelAnimationFrame(timer); timer = requestAnimationFrame(function fn(){ var oTop = document.body.scrollTop || document.documentElement.scrollTop; if(oTop > 0){ document.body.scrollTop = document.documentElement.scrollTop = oTop - 160; timer = requestAnimationFrame(fn); }else{ cancelAnimationFrame(timer); } }); }; /*********點贊功能**********/ //模擬原始點贊按鈕的點擊事件 var digg = document.getElementById('div_digg'); menuFavour.onclick = digg.children[0].onclick; //獲取贊成數的函數 function getfavourNum(){ favourNum.innerHTML = digg.children[0].children[0].innerHTML; } //頁面載入時獲取贊成數 getfavourNum(); menuFavour.addEventListener('click',function(){ setTimeout(function(){ getfavourNum(); },2000); }) /*********評論功能*********/ menuCommand.onclick = function(){ document.getElementById('comment_form_container').scrollIntoView(); } } </script>
當然,也可以直接引入js文件,文件線上地址為http://files.cnblogs.com/files/xiaohuochai/contextMenu.js
最後
如何演示?點擊右鍵就出現效果了
但是,在IE瀏覽器中,會提示無法獲取博客園文檔自動生成的<div class="diggit">元素,具體原因和解決辦法還不清楚
歡迎交流