首页 > 代码库 > 网页右键菜单开发

网页右键菜单开发

拉上窗帘,感慨良多。别让工作占据了所有的生活呀,朝九晚六,回家还能撸猫呀。,猫咪睡觉了,咱还能写代码呀,代码写完了,起码得写篇随笔显摆下呀,别只贴上代码就完事了,你还得介绍开发步骤和心得呀,这也是我这么晚了还来写这篇无聊的随笔的原因。

写代码不是工作,所以我基本是随心所欲,自己想到哪就写到哪,自己开心就好。看到百度云盘(网页版)上面文件夹的右键菜单,才注意到原来网页右键菜单可以人为改变的,于是洗干净粘满猫毛的双手,撸起了键盘,经过几次断断续续的尝试,撸出了一个DEMO。

既然是右键菜单,首先就要重写下右键单击的功能。先准备一个用来右键单击的元素:

<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>

效果图:

技术分享

技术分享

 

网页右键菜单开发