• 网页右键菜单开发


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

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

    效果图:

  • 相关阅读:
    BestCoder Round #32
    USACO Runaround Numbers
    USACO Subset Sums
    USACO Sorting a Three-Valued Sequence
    USACO Ordered Fractions
    USACO 2.1 The Castle
    Codeforces Round #252 (Div. 2)
    Codeforces Round #292 (Div. 2)
    BZOJ 1604: [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居
    BZOJ 1603: [Usaco2008 Oct]打谷机
  • 原文地址:https://www.cnblogs.com/dige1993/p/6096062.html
Copyright © 2020-2023  润新知