get clicks through html canvas

寵の児 提交于 2021-02-04 14:26:48

问题


I'm seeing a lot of questions about how to get the html5 canvas element to receive mouse clicks, I'm using the canvas as an overlay and the mouse clicks aren't going through to the elements below. I'm loading an image into the canvas, and I thought that might be the problem but I've also tried it with an empty canvas and I get the same result.

Here is an example: with the image: http://www.1luckypixel.com/paranormal/canvas_test.html the link goes to google but it's not registering.

It's my understanding that the canvas is transparent to the mouse by default?


回答1:


If cross browser functionality is not a requirement, then there is an easy solution. On browsers that support it for non SVG elements(webkit, Mozilla and maybe others, but notably not IE), you can use the css property called pointer-events. From the MDN:

"The CSS property pointer-events allows authors to control under what circumstances (if any) a particular graphic element can become the target of mouse events. When this property is unspecified, the same characteristics of the visiblePainted value apply to SVG content.

In addition to indicating that the element is not the target of mouse events, the value none instructs the mouse event to go "through" the element and target whatever is "underneath" that element instead.

Warning: The use of pointer-events in CSS for non-SVG elements is experimental. Currently defined in the CSS3 UI draft specification, there are discussion to postpone it to CSS4."

At the very least, you can use Modernizr to detect pointer-events support and do the opacity trick mentioned in Simon Sarris's answer on browsers that don't support it.

Also, if your application is specific to google maps, you can insert your canvas as a google maps overlay, thus avoiding the problem all together.

Example: http://www.patrick-wied.at/static/heatmapjs/demo/maps_heatmap_layer/gmaps.php




回答2:


Assuming you can't put the links above the canvas...

For new/decent browsers, simply use this CSS:

#canvas { pointer-events:none; }

And a dirty workaround for IE + older browsers (you could remove the dependency on jQuery):

jQuery('#canvas').click(function(e) {
    window.location = jQuery('#element-under-canvas').attr('href');
});

Obviously this only supports anchors as it stands, and you need to know the specific element under the canvas (or can find it using jQuery selector magic).




回答3:


I was able to accomplish this by setting the canvas like this:

<div>
    <a href='#'>my link</a>
    <canvas></canvas>
</div>

Then I set it to the following in CSS:

canvas {
    display: block;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    position: absolute;
    z-index:-1; /* NOT SURE HOW SUPPORTED THIS IS, IT WORKED IN CHROME */
}

The link within the div was clickable, regardless of anything I painted to the canvas at runtime.

Hope this helps!




回答4:


Well the short answer is that you cannot pass the click through.

But the second shortest answer is that you can indeed do anything your heart desires! You just have to be willing to get a little strange with the solution.

The first way I can think of is slightly maddening but easy: For every item behind the canvas, make a similar secret item in front of the canvas. Then put the event you want on the secret item:

<!-- A visible button behind the canvas -->
<button id="but" type="button" style="position: absolute; top: 100px; left: 100px;">Click Me!</button>

<canvas id="can" width="500" height="500" style="position: absolute;"></canvas>

<!-- A near copy of the visible button, but this one is invisible and in front of the canvas! -->
<button id="but" type="button" onclick="alert('click!')" style="position: absolute; top: 100px; left: 100px; opacity: 0;">Click Me!</button>

If you want to see that code in action click here

There are slightly more-insane-yet-more-maintainable ways if you have a hundred things behind the canvas you want to be clickable, but this is probably the easiest to do if you just have 1-3 things you want to click behind a canvas.




回答5:


Borrowing from Simon Sarris's answer, it may be simpler in some situations to have the canvas & controls be on the same plane. Depending on the control, it doesn't always allow the canvas to draw on top of the control, but this doesn't seem to be needed in Joe's original question. The important thing is to make sure the canvas and controls are on the same Z plane, both have a style using the "position" keyword, and have the HTML for the controls be after the canvas statement. The following is an example of a canvas combined with controls using this method.

<canvas id="can" width="500" height="500" style="z-index:2; position: absolute;"></canvas>
<!-- Put text and a link on the same plane as the canvas -->
<div style="position: relative; z-index: 2;">
   <a href="http://www.google.com/">Click</a> this Google link.
</div>



回答6:


I'm not sure how the procedure for this goes but Simon Sarris actually provided the solution in the comments:

Unfortunately my other method won't work in this instance. :( However, you could still mess with opacities until you have something close to what you want. Here's an example of transparent map showing a canvas behind it. It appears as if the green box is on top but it is really just showing through: jsfiddle.net/un9yW/11 Of course, doing this method means there is no way of making a green box to completely cover part of the map, and so on, which is kind of lame. I'll let you know if I think of anything else that will work for your situation. – Simon Sarris 7 hours ago




回答7:


Here's how I solved this problem...

I have a round user interface device (drawn on a plain HTML5 canvas, which is a square). Only the circle is colored, the rest of the canvas is transparent, and I want to click through it. Under the corners of the square canvas, there are shapes on a Kinetic JS stage.

Normally you cannot click through a canvas.

But you can send the click event through to a Kinetic shape, and activate event listeners within that shape like this:

    $( '#myCanvasUserInterfaceLayer' ).on( 'click', function( e ) {

        var pos = getMousePos( e );
        var obscuredKineticShape = kineticLayer.getIntersection( pos );

   // (Note: console.log(obscuredKineticShape) and you find that 
   // 'getIntersection' returns an object with the topmost shape 
   //  at the click point on the kinetic stage within it, called 'shape').

        obscuredKineticShape.shape.fire( 'mousedown' ); 

    });

     function getMousePos( e ) {

        return {
          x: e.pageX,
          y: e.pageY
        };
      }



回答8:


I think it's better to change z-index dynamically. If you need to use controls set their z-index higher than canvas. If you need to use canvas - set it's z-index higher than controls. Exact way how to do this depends of your situation. You may listen for mousedown/mouseup events, or for mousemove over some areas.



来源:https://stackoverflow.com/questions/3615533/get-clicks-through-html-canvas

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!