Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass click event to an element underneath

I have a full-screen transparent canvas covering my web page. On the canvas, I render an interactive object. There's a problem: elements (e.g. links) below the canvas do not respond to mouse clicks.

The obvious solution, which I would normally use, is to apply pointer-events: none to the canvas. This will allow clicks to pass through. However, this doesn't work in this situation, because I want the interactive object to be clickable.

So here's what I want to do:
The canvas should retain mouse-click events. IF the event is NOT over the interactive object, it should pass the event to the elements on the other side of the page.

How can I do this?

like image 558
Timothy Smith Avatar asked May 24 '16 00:05

Timothy Smith


2 Answers

Found a really nice solution that I thought I should share in case anybody else has the same question.

I used pointer-events: none on the canvas. I set canvas.onclick and canvas.onmousemove like I normally would; however, pointer events are disabled so nothing happens. I bypassed the disabled pointer events like this:

document.addEventListener('click', function() {
 canvas.onclick();
});
window.onmousemove = function() {
 canvas.onmousemove();
}
// etc.

So far, mouse events will be received by both the web page AND the canvas.

Now, in my interactive program, I included a simple little function called "mouseOver" which returns true if the mouse is hovering over the interactive object. I modified window.onmousemove like this:

window.onmousemove = function() {
 canvas.onmousemove(); 
 if (mouseOver()) {
  canvas.style["pointer-events"] = "auto";
 } else {
  canvas.style["pointer-events"] = "none";
}};

This prevents mouse events from going through to the web page, allowing interaction with the object without webpage interference.

like image 109
Timothy Smith Avatar answered Sep 29 '22 02:09

Timothy Smith


Every event that is captured goes through two stages,

1) capturing (where it is propagated to the children) 2) bubbling (where it is sent back up to the parent)

by default, capturing is disabled. you can you use addEventListener("click", function(){blah blah blah}, true) which would pass the event to its children.

in the child element, you can handle the event as you wish.

Here's a sample code that i created by editing http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_element_addeventlistener

<!DOCTYPE html>
<html>
  <body>

    <p>This example uses the addEventListener() method to attach a click event to a button.</p>
    <div id="myBtn">
      <button id="myBtn2">Try it</button>
    </div>

    <p><strong>Note:</strong> The addEventListener() method is not supported in Internet Explorer 8 and earlier versions.</p>

    <p id="demo"></p>

    <script>
    document.getElementById("myBtn").addEventListener("click", function(){
                if(true){
                  document.getElementById("demo").innerHTML = "Hello World";
                  event.stopPropagation();
                }
              }, true);

    document.getElementById("myBtn2").addEventListener("click", function(){
              document.getElementById("demo").innerHTML += "Hello World2";
              });
    </script>

  </body>
</html>

In this case, parent div captures the event and if it acts on it, it stops propagation. otherwise it just sends it to its child who is in-turn listening to it. Hope this helps

Source - http://javascript.info/tutorial/bubbling-and-capturing

like image 41
Ravi Sankar Raju Avatar answered Sep 29 '22 02:09

Ravi Sankar Raju