您的位置:首页 > Web前端

ife系列之自定义鼠标右键菜单

2017-03-02 20:34 204 查看

ife系列之自定义鼠标右键菜单

问题引出:

  日常浏览网页时,鼠标右键的菜单栏不可缺少,但在有些项目中需要取消浏览器默认的右键菜单,在指定的区域可以自定义右键菜单栏,来满足实际的需要。今天就探讨一下,关于自定义鼠标右键菜单栏的事情。

就目前来说,要实现自定义鼠标右键菜单栏,以下的几个地方需要着重思考一下:

 1)如何禁用浏览器默认的右键菜单(受浏览器差异影响);

 2)如何触发鼠标右键的点击事件(受浏览器差异影响);

 3)如何将自定义的菜单显示出来;

 4)如何计算显示在指定区域;

那么,在讲这几个问题之前先说一下,一般浏览器的事件获取机制?(分别在Chrome 55.0.2883.87 (64-bit)、Firefox 50.1.0、IE8环境下测试,下面简称为chrome、Firefox、ie)

 1.在chrome下既可以通过参数传递获取事件(显式传递的第一个参数),也可以直接获得全局事件对象window.event

 2.在Firefox下只可以通过参数传递获取事件(显式传递的第一个参数)

 3.在ie下是直接获取全局事件对象window.event

 4.综合上述,我们通常这样写
e = e || window.event;


下面就结合这几个问题来展开:

 

  1)首先第一个问题:如何禁用浏览器默认的右键菜单(受浏览器差异影响)?

  答:要想取消浏览器默认的右键菜单,可以使用
e.returnValue = false
(其实return false也是可以的,但不是用这种方式)或
e.preventDefault()
来阻止默认事件的发生,但是需要考虑兼容性的问题,所以我们可以这么来写
e.preventDefault ? e.preventDefault() : e.returnValue = false;
见下图:


  2)继续第二个问题:如何触发鼠标右键的点击事件(受浏览器差异影响)?

  关于事件的触发,实现的方式也受浏览器差异的影响,最折中的方式是使用事件函数绑定的方式来做兼容性处理(但是楼主没有测试环境,需要ie8以下版本的浏览器,这里就不测试了,只用onXXX的方式),见下图:

  


  算了,还是讲一下兼容性的处理方式,见下图:

  


  3)然后第三个问题:如何将自定义的菜单显示出来?

   由于使用
display:none;
的方式会导致该元素不参与页面的渲染,这样就无法获取自定义菜单的宽、高,其实首次加载预先保存元素的宽、高也可以,但采用
visibility:hidden;
也是可以的,相对来说,既简单又好理解。见下图:

   


 4)最后第四个问题:如何计算显示在指定区域?

   这个问题关键就是逻辑,你要保证自定义菜单永远显示在指定区域,而不能超越边界,因此,我这样定义显示的逻辑:

   

 

   

好了,上面是几个关键步骤的讲解,下面上完整代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>自定义网页右键菜单</title>
<style type="text/css">
/*去除默认边界*/
div, ul{
margin: 0;
padding: 0;
}
/*去除列表默认样式*/
ul, li{
list-style: none;
}
/*Start div*/
.div{
position: relative;
width: 800px;
height: 400px;
/*overflow: hidden;*/
}
/*Start dv1*/
.dv1{
width: 800px;
height: 400px;
background: #F5F5F5;
border: 1px solid #CCC;
border-radius: 5px;
text-align: center;
line-height: 402px;
font-size: 26px;
z-index: 1;
}
/*End dv1*/
/*Start dv2*/
.dv2{
position: absolute;/*相对于父级元素,实现绝对定位*/
width: 200px;
height: 100px;
color: #F16B41;
border: 1px solid #000;
border-radius: 5px;
visibility: hidden;/*使用visibility控制元素的显隐*/
z-index: 999;
background: #FFF;
}
.dv2 > li{
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
font-size: 16px;
}
.dv2 > li:hover{
background: #F16B41;
cursor: pointer;
color: #FFF;
}
.dv2 > li:nth-child(1){
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.dv2 > li:nth-child(2){
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
/*End dv2*/
/*End div*/
</style>
</head>
<body>
<div class="div">
<!--右键点击有效区域-->
<div class="dv1" id="dv1">
<label>Right click to see menu</label>
</div>

<!--自定义右键菜单栏-->
<ul class="dv2" id="dv2">
<li>Menu Item1</li>
<li>Menu Item2</li>
</ul>
</div>

<!--javascript代码-->
<script type="text/javascript">
window.onload = function(){
var div = document.getElementById("dv1");
var contextMenu = document.getElementById("dv2");

//用户点击右键时,计算显示位置后将右键自定义菜单显示
div.oncontextmenu = function(e){//获取点击坐标事件源
e = e || window.event;
// console.log("坐标:(" + e.offsetX + "," + e.offsetY + ")");
var result = calMenuPosition(e.offsetX, e.offsetY);//计算显示位置
contextMenu.style.left = result.left + "px";//别忘了加上"px",^_^
contextMenu.style.top = result.top + "px";
contextMenu.style.visibility = 'visible';//显示
e.preventDefault ? e.preventDefault() : e.returnValue = false;
}

//用户点击左键时,将右键自定义菜单隐藏
div.onclick = function(e){
e = e || window.event;
contextMenu.style.visibility = 'hidden';//隐藏
e.stopPropagation();//解决方式:在子元素触发的事件中,取消事件冒泡(此写法只适用于Firefox和chrome等浏览器)
e.cancelBubble = true;//兼容IE,取消事件冒泡
}

//全局取消右键的默认操作
document.oncontextmenu = function(e){
e = e || window.event;//兼容IE8、FireFox、chrome
e.preventDefault ? e.preventDefault() : e.returnValue = false;//三目运算符进行兼容性判断
}
}

/**
* @function 计算自定义右键菜单栏的显示位置
* @describe 实现逻辑如下:
*              假设高度足够,若宽度足够,显示在右下方
*                            若宽度不够,显示在左下方
*              假设高度不够,若宽度足够,显示在右上方
*                            若宽度不够,显示在左上方
*
* @param x 右键点击时x轴坐标
* @param y 右键点击时y轴坐标
* @return left 计算后left的值
*         top 计算后top的值
*/
function calMenuPosition(x, y){
var div = document.getElementById("dv1");
var div_width = div.clientWidth || div.offsetWidth - 2;//右键有效区域宽度
var div_height = div.clientHeight || div.offsetHeight - 2;//右键有效区域高度

var contextMenu = document.getElementById("dv2");
var con_width = contextMenu.clientWidth || contextMenu.offsetWidth - 2;//自定义菜单栏的宽度
var con_height = contextMenu.clientHeight || contextMenu.offsetHeight - 2;//自定义菜单栏的高度

var conX = 0, conY = 0;//待计算设置坐标

//进行逻辑判断
if(y + con_height <= div_height){//高度足够
if(x + con_width <= div_width){//宽度足够
conX = x;
conY = y;
}else{//宽度不够
conX = x - con_width;
conY = y;
}
}else{//高度不够
if(x + con_width <= div_width){//宽度足够
conX = x;
conY = y - con_height;
}else{//宽度不够
conX = x - con_width;
conY = y - con_height;
}
}

//返回计算结果
return{
'left' : conX,
'top' : conY
}
}
</script>
</body>
</html>


以上便是完整的代码,关于此篇文章的学习笔记和其他代码还可以参见楼主的github地址,ok,有问题的小伙伴,可以留言交流,周末愉快^_^!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  鼠标 浏览器