我的画布上附有鼠标移动事件监听器。但是在我的画布上面是一个具有更高z-index的div,它包含一些菜单按钮。
我面临的问题是,我希望鼠标移动事件在鼠标悬停在菜单元素上时仍然激活 - 该元素位于画布元素之上。
目前,它的作用就好像鼠标不再位于画布顶部,因为菜单元素因z-index顺序而优先。
有没有办法让这个事件监听器忽略任何阻碍的元素?
我的代码:
var canvas = new function(){
var self = this
self.outputMouseData = function(evt,el){
var pos = mouse.relativePosition(evt,el);
el.ctx.clearRect(0,0,el.width,el.height);
el.ctx.fillStyle = "white";
el.ctx.font = "bold 16px Arial";
el.ctx.fillText(pos.x+' | '+pos.y, el.width-150,el.height-10);
}
}
elements.addEvent(foreground,'mousemove',
function(evt){ canvas.outputMouseData(evt,foreground); }
);
我的HTML
<div class="parent">
<canvas id="canvas"></canvas>
<div class="menu">Menu output</div>
</div>
父母是相对定位的。画布和菜单是绝对定位的,但菜单在画布上是z-index'd。
答案 0 :(得分:3)
HTML事件正在冒泡节点树(你可以阅读关于here的一个很好的解释)。
这意味着如果将事件处理程序附加到包含其他元素的元素,则当子元素上发生事件时,该处理程序将被称为甚至(给定冒泡未明确中止) )。你可以包装你的画布&amp; div包装元素(例如span)并在其上附加处理程序。无论z-index如何,你都会得到这个事件。
以下是代码外观的简短示例(取自here的getOffsetSum):
var canvas = document.getElementById('canvas');
var canvasPos = getOffsetSum(canvas);
var ctx = canvas.getContext('2d');
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect(0, 0, 99, 99);
var container = document.getElementById('container');
var mousemove = document.getElementById('mousemove');
container.addEventListener('mousemove', function(evt) {
var pos = getOffsetSum(evt.target);
pos.top += evt.offsetY - canvasPos.top;
pos.left += evt.offsetX - canvasPos.left;
mousemove.innerHTML = 'offsetX: ' + evt.offsetX + ' | offsetY: ' + evt.offsetY + '<br/>' +
'canvasX: ' + pos.left + ' | canvasY: ' + pos.top;
});
function getOffsetSum(elem) {
var top = 0, left = 0;
while (elem) {
top = top + parseInt(elem.offsetTop);
left = left + parseInt(elem.offsetLeft);
elem = elem.offsetParent;
}
return {
top: top,
left: left
}
}
.ontop {
position: absolute;
top: 20px;
left: 20px;
}
<span id="container">
<canvas id="canvas" width="100" height="100"></canvas>
<div class="ontop">ON TOP</div>
</span>
<div id="mousemove"></div>
答案 1 :(得分:1)
将canvas和menu-div放入容器div中。
然后使用jQuery事件委托来侦听容器上的mousemove事件,但让画布响应那些mousemove事件。
$('#container').on('mousemove','#myCanvas',function(){ doSomething(); }
您可以在此处详细了解活动授权:http://api.jquery.com/on/
答案 2 :(得分:0)
我最初的想法是将“mousemove”事件添加到文档本身(而不是canvas元素或元素),并使用evt.currTarget或evt.target跟踪元素。通过这种方式,无论您将鼠标悬停在菜单或画布上(或任何地方),mousemove evt都将始终存在。
答案 3 :(得分:0)
您不必像其他答案中那样使用包装器,只需将pointer-events: none;
应用于菜单div。这将允许画布发出mousemove
事件。
.menu {
pointer-events: none;
}