既然是右键菜单,首先就要重写下右键单击的功能。先准备一个用来右键单击的元素:
<div id="test"></div>
简要定义下高度、宽度和背景色:
#test { width:200px; height:200px; background-color:green; }
接下来就来编写这个div的右键单击事件,由于元素默认都有右键菜单,所以我们首先要去掉默认默认菜单:
//去掉默认的contextmenu事件,否则会和右键事件同时出现。 document.getElementById("test").oncontextmenu = function(e){ e.preventDefault(); };
然后重新定义鼠标单击操作:
document.getElementById("test").onmousedown = function(e){ //右键 if(e.button ==2){ alert("你点击了右键"); }else if(e.button ==0){ //左键 alert("你点击了左键"); }else if(e.button ==1){ //按下滚轮 alert("你按下了滚轮"); } }
如上,各个键的单击的功能都改写了下,写右键菜单的话,我们只需要将显示菜单的代码放在e.button == 2的情况下就行。
改写了右键单击的功能,接下来要做显示菜单的功能,首先准备几个简单的元素构成菜单:
<ul class="context-menu" id="ct"> <li class="context-menu-item">option1</li> <li class="context-menu-item">option2</li> <li class="context-menu-item">option3</li> </ul>
同样加上简单的样式使它看起来更像样点:
ul.context-menu { padding:0; margin:0; position:absolute; /*只能是absolute或fixed*/ } ul.context-menu li { list-style:none; width:100px; height:20px; line-height:20px; text-align:center; border:solid 1px; background-color:#CCC; display:block; } ul.context-menu li:hover { background-color:#C0C0C0; cursor:context-menu; }
到这里,网页基本上是这个样子:
哦,一开始菜单应该是隐藏的,所以应该给ul加上display:none;属性,这样网页上一开始就只能看到绿色的方块:
ul.context-menu { padding:0; margin:0; display:none; position:absolute; /*只能是absolute或fixed*/ }
然后改写绿色方块的右键单击事件,使得右键单击时菜单得到显示,前面说过了,只要将显示菜单的代码写到e.button == 2的情况下面就好了,像这样:
if(e.button ==2){ document.getElementById("ct").style.display = "block"; }
这个时候的基本样子就是打开页面看到一个绿色方块,右键单击绿色方块,左上角出现菜单。右键菜单有一个基本特性就是菜单显示后,若鼠标再点在菜单以外的其它地方,菜单应该隐藏,所以我们还应该重写下这个方块的左键单击事件、中键单击事件、失去焦点事件(鼠标点在绿色方块以外),在这些事件中加上隐藏菜单的代码,基本上就像这样:
document.getElementById("test").onmousedown = function(e){ //右键 if(e.button ==2){ document.getElementById("ct").style.display = "block"; }else if(e.button ==0){ //左键 document.getElementById("ct").style.display = "none"; }else if(e.button ==1){ //按下滚轮 document.getElementById("ct").style.display = "none"; } } //失去焦点事件 document.getElementById("test").onblur = function(e){ document.getElementById("ct").style.display = "none"; }
这个时候已经基本像样了,打开页面,会看到一个绿色方块,右键单击方块,左上角会显示菜单,鼠标再点菜单以外其它地方,菜单会消失,有点味道了。右键菜单还有一个基本属性,就是菜单位置紧跟鼠标点击的位置,所以我们在右键单击事件中,还需要加上给菜单定位的代码,为了能通过X、Y定位,菜单的posiotion设置成absolute或fixed是很有必要的,建议absolute。这个时候右键单击事件的处理代码基本上像这样:
if(e.button ==2){ var x = e.clientX;//获取鼠标单击点的X坐标 var y = e.clientY;//获取鼠标单击点的Y坐标 //设置菜单的位置 document.getElementById("ct").style.left = x + "px"; document.getElementById("ct").style.top = y + "px"; document.getElementById("ct").style.display = "block"; }
到这里,页面基本上已经很有味道了,右键在绿色方块内任意地方单击,就会在该地方显示菜单,鼠标再点菜单以外其它地方,菜单会消失。
接下来,很重要的一点,就是鼠标移入菜单内的时候,我们必须取消绿色方块失去焦点时隐藏菜单的功能。因为在点击菜单项的时候,会先触发绿色方块的失去焦点(onblur)事件,然后才触发onclick事件,我们在前面定义了方块失去焦点就隐藏菜单的,而菜单被隐藏(display被设置成none,基本等同从页面移除了这个元素)时,它的onclick事件就不会被触发了;所以我们要想办法在菜单项的onclick事件被触发前阻止绿色方块的onblur事件被触发,基本解决办法就是在鼠标移到菜单项上面时取消方块的onblur事件,鼠标移出菜单项时恢复方块的onblur事件,像这样:
//给每个菜单项添加事件处理 var items = document.getElementsByClassName("context-menu-item"); for(var i=0; i < items.length; i++){ //在定义onclick事件之前,必须设置取消test元素的onblur事件,否则onclick事件失效,因为click先触发的是test元素的onblur事件,该事件有移除菜单的操作,才会导致后面的代码失效 items.item(i).onmouseover = function(e){ document.getElementById("test").onblur = undefined; } //鼠标移出菜单时,还是要将test的onblur事件还原 items.item(i).onmouseleave = function(e){ document.getElementById("test").onblur = function(e){ document.getElementById("ct").style.display = "none"; } } }
处理好这个细节,我们就可以放心大胆地写菜单的功能了,功能根据实际需要来写,这里就没什么好介绍的了。
哦,还有一个细节要处理,就是代码写到这里,右键单击方块的时候会同时出现系统默认菜单和我们自己的菜单,这是因为右键单击的时候同时触发了菜单元素的右键单击事件,我们同时要屏蔽菜单元素的右键默认事件:
document.getElementById("ct").oncontextmenu = function(e){ e.preventDefault(); };
到这里,基本所有细节都介绍到了,接下来最重要的就是将上面这些细节组装成完整的DEMO了,示例如下:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>网页右键菜单</title> <!-- 思路: 1.写出右键点击事件; 2.写出菜单功能; 3.关联右键功能和菜单,学习使用定位 --> <style> #test { width:200px; height:200px; background-color:green; } ul.context-menu { padding:0; margin:0; display:none; position:absolute; /*只能是absolute或fixed*/ } ul.context-menu li { list-style:none; width:100px; height:20px; line-height:20px; text-align:center; border:solid 1px; background-color:#CCC; display:block; } ul.context-menu li:hover { background-color:#C0C0C0; cursor:context-menu; } </style> <script> //var t = document.getElementById("test"); window.onload = function(){ var clicked_ele;//全局变量,用于记录被右键单击呼出菜单的元素 //去掉默认的contextmenu事件,否则会和右键事件同时出现。 document.getElementById("test").oncontextmenu = function(e){ e.preventDefault(); }; document.getElementById("ct").oncontextmenu = function(e){ e.preventDefault(); }; document.getElementById("test").onmousedown = function(e){ if(e.button ==2){//右键 var x = e.clientX;//获取鼠标单击点的X坐标 var y = e.clientY;//获取鼠标单击点的Y坐标 //设置菜单的位置 document.getElementById("ct").style.left = x + "px"; document.getElementById("ct").style.top = y + "px"; document.getElementById("ct").style.display = "block"; clicked_ele = this; }else if(e.button ==0){ //左键 document.getElementById("ct").style.display = "none"; }else if(e.button ==1){ //按下滚轮 document.getElementById("ct").style.display = "none"; } } document.getElementById("test").onblur = function(e){ document.getElementById("ct").style.display = "none"; } //给每个菜单项添加事件处理 var items = document.getElementsByClassName("context-menu-item"); for(var i=0; i < items.length; i++){ //在定义onclick事件之前,c必须设置取消test元素的onblur事件,否则onclick事件失效,因为click先触发的是test元素的onblur事件,该事件有移除菜单的操作,才会导致后面的代码失效 items.item(i).onmouseover = function(e){ document.getElementById("test").onblur = undefined; } //鼠标移出菜单时,还是要将test的onblur事件还原 items.item(i).onmouseleave = function(e){ document.getElementById("test").onblur = function(e){ document.getElementById("ct").style.display = "none"; } } items.item(i).onclick = function(e){ e.stopPropagation();//为避免引起其它错误,阻止冒泡很重要 console.log(this.innerHTML + ":" + clicked_ele.innerHTML); document.getElementById("ct").style.display = "none"; } } } </script> </head> <body> <ul class="context-menu" id="ct"> <li class="context-menu-item">option1</li> <li class="context-menu-item">option2</li> <li class="context-menu-item">option3</li> </ul> <div id="test" tabindex="2">我是美腻大方的绿方块</div> </body> </html>
效果图: