2015-08-06 2 views
0

У меня есть прослушиватель событий перемещения мыши, прикрепленный к моему холсту. Но поверх моего холста есть div с более высоким z-индексом, в нем есть некоторые кнопки меню.Слушатель событий на холсте за другим элементом

Проблема, с которой я сталкиваюсь, я хочу, чтобы событие перемещения мыши продолжало активироваться, когда мышь находится над элементом меню, который находится над элементом холста.

В настоящее время он действует так, как будто мышь больше не находится поверх холста, потому что элемент меню имеет приоритет из-за порядка z-индекса.

Есть ли способ заставить слушателя этого события игнорировать любые элементы, которые мешают?

Мой код:

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

Если наложение является дочерним элементом, вы можете использовать addeventlistener с истинным в качестве третьего параметра, он должен активировать родительское событие. – David

+0

Canvas 'не имеет дочерних элементов. Меню позиционируется абсолютным внутри родителя, который является относительным. – Sir

+0

- sry это предназначалось для добавления оценок. Ну, я вижу, у вас есть решение! – David

ответ

2

HTML-события пузырятся по дереву узлов (вы можете прочитать хорошее объяснение об этом here).

Что это означает, что если вы приложите обработчик событий к элементу, который содержит другие элементы, что обработчик вызывается даже, когда событие происходит на дочерний элемент (при пузыриться не был явно прервана). Вы можете обернуть ваш холст & div в элемент оболочки (например, span) и приложить к нему обработчик. Вы получите событие независимо от z-индекса.

Вот краткий пример того, что код может выглядеть следующим образом (в getOffsetSum взятого из here):

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>

+0

Но смогу ли я получить положение мыши относительно холста так? Что делать, если холст был смещен внутри родительского div - это бы усложнило это немного наверняка? – Sir

+0

Возможно, но так как вы создадите обертку div, единственной целью которой является получение событий, вы можете сделать ее точно такой же размер и положение. Кроме того, не так уж страшно корректировать координаты X/Y для элемента. – Amit

+0

Благодарим вас за пример, позор этой проблемы в javascript не имеет изящного решения, встроенного в этот язык, но пока это работает хорошо! – Sir

1

Помещенных как холст и ваше меню DIV в контейнере DIV ,

Затем используйте делегацию событий jQuery для прослушивания событий mousemove в контейнере, но ваш холст отвечает на эти события mousemove.

$('#container').on('mousemove','#myCanvas',function(){ doSomething(); } 

Вы можете узнать больше о делегировании событий здесь: http://api.jquery.com/on/

+0

Это полезно, но я не использую jquery. Я использую vanilla JS. – Sir

+0

Вы можете выполнить делегирование событий с помощью vanilla JS. Это просто сложнее, потому что вам нужно вручную управлять пузырьком событий. Лично я использую jQuery для упрощения делегирования, поэтому вы можете попросить @Amit провести вас через версию ванили. Удачи с вашим проектом! – markE

0

Мои первоначальные мысли было добавить «MouseMove» событие самого документа (вместо холста элемента или элементов), а также отслеживать элементы используя evt.currTarget или evt.target. Таким образом, mousemove evt всегда будет присутствовать, нависнете ли вы над меню или холстом (или где угодно, если на то пошло).

+0

Но это активирует событие, даже если я перемещаю мышь, если не поверх холста. – Sir

+0

Точно, я думаю, что это то, чего вы ожидали, правильно? вы всегда будете получать mousemove evt, когда находитесь над холстом или когда вы находитесь над элементом меню. Вам нужно будет вызывать ваши методы только в том случае, если мышь event.target является холстом или элементом меню. Кроме того, вы можете добавить родительский div, который охватывает как меню, так и холст, и добавляет событие mousemove для родительского div. – user3329460

+0

Нет, я только хотел, чтобы он активировался, когда мышь находится в границах холста, а не всего окна. – Sir

Смежные вопросы