html canvas trap left click and allow right click

2019-08-26 20:26发布

问题:

The use case is that I have an html canvas on top of several html elements which listen for right click mouse events. I want to draw on the canvas using left mouse button, and at the same time interact with underlying html elements using right click.

I get that I can allow all mouse events to pass through the canvas by setting css property pointer-events to none. However I want to allow only right click to pass through it.

One way to achieve this may be to listen on the canvas for right click, set pointer-events to none in the callback, manually fire a right click event again and set pointer-events back to auto.

Btw I'm using KineticsJS and I have no idea how to manually fire mouse events using it.

Any suggestions would be appreciated.

回答1:

Interesting subject that caught my attention. It was fun to come up with a solution to it based on this jQuery approach and some others. I'm not familiar with KineticsJS, but this is a plain javascript approach

In essence you can fake a pointer-events:none for just the right click by using the object's dimensions/positioning and onmousedown's event.which to determine if a right click was clicked on the background elements. The following is an example of that approach, hopefully the comments explain it well

// Get all overlaying canvases
var canvas = document.getElementsByTagName("canvas"), 
// Get all elements that you want the click to fire on
    background = document.getElementsByClassName("background"); 

// Use click location and dimensions/positioning to fake a click through
function passThrough(e) { 
    // Allow only right click to pass through
    if(e.which == 2 || e.which == 3) { 
        // Check all background elements
        for(var i = 0; i < background.length; i++) { 
            // check if clicked point (taken from event) is inside element
            var mouseX = e.pageX;
            var mouseY = e.pageY;
            var obj = background[i];
            var width = obj.clientWidth;
            var height = obj.clientHeight;

            if (mouseX > obj.offsetLeft && mouseX < obj.offsetLeft + width 
                && mouseY > obj.offsetTop && mouseY < obj.offsetTop + height) {
                // Force click event if within dimensions
                background[i].onclick(); 
            }
        }
    }
}

for(var i = 0; i < canvas.length; i++) {
    // Force our function when clicked
    canvas[i].onmousedown = passThrough; 
    // Prevent menu from appearing
    canvas[i].oncontextmenu = function(event) { event.returnDefault; return false; } 
}
for(var i = 0; i < background.length; i++) {
    // Toggle background when clicked (to show it works)
    background[i].onclick = function() { 
        if(this.style.background == "black") {
            this.style.background = "red";
        }
        else {
            this.style.background = "black";
        }
    }
}

I hope it suits your needs!