摘要:
我们经常在网上能够看到点击鼠标右键弹出自定义的菜单项,自定义菜单可以使菜单项的样式和网站主题相似,开发自己需要的功能。本文分享了自己制作的右键菜单项,其主要特点是,当菜单项超出浏览器的可视区域时,改变菜单项的显示位置。
/*技术难点*/
1、获取文本的高度和宽度
使用window.getComputedStyle()方法获取的是auto值,并不是具体的值,无法实现当超出可视区域换方向
解决方法:
计算每一个li元素的高度和宽度,最终宽度取最大宽度,高度是每个li元素的高度之和加上边距
2、获取浏览器可视区域的高度
使用document.body.clientHeight获取的值为0,因为页面没有内容,理所当然高度为0
解决方法:
使用document.documentElement.clientHeight来计算浏览器的可视区域高度
DEMO:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <title>ContextMenu</title> 6 <style> 7 #contextMenu {border:1px solid rgb(219,219,219); position:absolute;margin:5px;padding: 0;} 8 #contextMenu li{list-style:none;margin-bottom: 5px;cursor:pointer;background-color: rgb(255, 174, 0);border-bottom: 1px solid #fff;} 9 </style> 10 </head> 11 <body> 12 <script> 13 // 菜单列表 14 var menuList = [ 15 { 16 'text': '刷新', 17 'id': 'one' 18 },{ 19 'text': '复制', 20 'id': 'two' 21 },{ 22 'text': '剪切', 23 'id': 'three' 24 },{ 25 'text': '重新加载', 26 'id': 'four' 27 } 28 ]; 29 // 获取菜单的宽和高 30 function getStyle(list) { 31 var wid = 0,hei = 0; 32 for(var i = 0, l = list.length; i < l; i++) { 33 var res = textSize(list[i].text); 34 if(res.width > wid) { 35 wid = res.width 36 } 37 hei += res.height; 38 } 39 // 加上间距 40 hei += i*5+20; 41 wid += 10; 42 return { 43 wid: wid, 44 hei: hei 45 }; 46 } 47 // 右键点击显示菜单项 48 document.oncontextmenu=function(ev){ 49 // 如果菜单项已经存在了,则删除 50 var ctx=document.getElementById('contextMenu'); 51 if(ctx) { 52 ctx.parentNode.removeChild(ctx); 53 } 54 var menu = document.createElement('ul'); 55 menu.id = 'contextMenu'; 56 menu.style.display = 'none'; 57 for(var i = 0, l = menuList.length; i < l; i++) { 58 var list=document.createElement("li"); 59 list.id = menuList[i].id; 60 var node=document.createTextNode(menuList[i].text); 61 list.appendChild(node); 62 menu.appendChild(list); 63 } 64 document.getElementsByTagName('body')[0].appendChild(menu); 65 var 66 l,t, 67 eve = ev||event, 68 sty = getStyle(menuList), 69 wid = parseInt(sty.wid), 70 hei = parseInt(sty.hei); 71 l = eve.clientX+wid>document.body.offsetWidth ? eve.clientX - wid : eve.clientX; 72 t = eve.clientY+hei>document.documentElement.clientHeight ? eve.clientY - hei : eve.clientY; 73 menu.style.left = l+'px'; 74 menu.style.top = t+'px'; 75 menu.style.display = 'block'; 76 return false; 77 } 78 // 当点击页面时,删除菜单项 79 window.onclick=function (event) 80 { 81 var ctx=document.getElementById('contextMenu'); 82 if(ctx) { 83 if(event.target.parentNode.id === 'contextMenu') { 84 ctx.style.display = 'none'; 85 alert('你点击了'+event.target.innerText); 86 }; 87 ctx.parentNode.removeChild(ctx); 88 } 89 }; 90 function textSize(text) { 91 //计算一段文本的真实长度和高度 92 var span = document.createElement("span"); 93 var result = {}; 94 result.width = span.offsetWidth; 95 result.height = span.offsetHeight; 96 span.style.visibility = "hidden"; 97 document.getElementsByTagName('body')[0].appendChild(span); 98 if(typeof span.textContent !== "undefined"){ 99 span.textContent = text; 100 } else { 101 span.innerText = text 102 } 103 result.width = span.offsetWidth - result.width; 104 result.height = span.offsetHeight - result.height; 105 span.parentNode.removeChild(span); 106 return result; 107 } 108 </script> 109 </body> 110 </html>