通过 html 画布获得点击次数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3615533/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 04:20:01  来源:igfitidea点击:

get clicks through html canvas

htmlcanvasmouse

提问by JoeM05

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.

我看到很多关于如何让 html5 canvas 元素接收鼠标点击的问题,我使用画布作为叠加层,并且鼠标点击不会传递到下面的元素。我正在将图像加载到画布中,我认为这可能是问题所在,但我也用空画布进行了尝试,但得到了相同的结果。

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

这是一个例子:使用图像:http: //www.1luckypixel.com/paranormal/canvas_test.html链接转到谷歌,但它没有注册。

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

我的理解是默认情况下画布对鼠标是透明的?

采纳答案by Bojin Li

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:

如果不需要跨浏览器功能,那么有一个简单的解决方案。在支持非 SVG 元素的浏览器(webkit、Mozilla 和其他可能,但特别是不支持 IE)的浏览器上,您可以使用名为pointer-events的 css 属性。来自 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.

“CSS 属性 pointer-events 允许作者控制在什么情况下(如果有)特定图形元素可以成为鼠标事件的目标。当未指定此属性时,visiblePainted 值的相同特征适用于 SVG 内容。

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.

除了指示该元素不是鼠标事件的目标之外,值 none 指示鼠标事件“通过”该元素并以该元素“下方”的任何内容作为目标。

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."

警告:在 CSS 中为非 SVG 元素使用指针事件是实验性的。目前在 CSS3 UI 草案规范中定义,有讨论将其推迟到 CSS4。

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

至少,您可以使用 Modernizr 来检测指针事件支持,并在不支持它的浏览器上执行Simon Sarris 的回答中提到的不透明技巧。

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

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

回答by Dunc

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

假设你不能把链接放在画布上方......

For new/decent browsers, simply use this CSS:

对于新的/不错的浏览器,只需使用此 CSS:

#canvas { pointer-events:none; }

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

还有一个针对 IE + 旧浏览器的肮脏解决方法(您可以删除对 j​​Query 的依赖):

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).

显然这仅支持锚点,并且您需要知道画布下的特定元素(或者可以使用 jQuery 选择器魔术找到它)。

回答by Steve Woods

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:

然后我在 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.

div 中的链接是可点击的,无论我在运行时在画布上画什么。

Hope this helps!

希望这可以帮助!

回答by Simon Sarris

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 itemin 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.

如果画布后面有一百个东西想要点击,那么还有一些更疯狂但更易于维护的方法,但是如果你只有 1-3 个东西想要点击,这可能是最简单的方法帆布。

回答by Frank

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.

借用 Simon Sarris 的回答,在某些情况下,将画布和控件放在同一平面上可能会更简单。根据控件的不同,它并不总是允许画布在控件之上绘制,但这在 Joe 的原始问题中似乎不需要。重要的是确保画布和控件在同一个 Z 平面上,两者都具有使用“位置”关键字的样式,并且控件的 HTML 位于 canvas 语句之后。以下是使用此方法结合控件的画布示例。

<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>

回答by JoeM05

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

我不确定这个过程是如何进行的,但 Simon Sarris 实际上在评论中提供了解决方案:

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/11Of 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

不幸的是,我的其他方法在这种情况下不起作用。:( 但是,您仍然可能会弄乱不透明度,直到您拥有接近您想要的东西为止。这是一个透明地图的示例,显示其背后的画布。看起来好像绿色框在顶部,但它实际上只是显示出来: jsfiddle.net/un9yW/11当然,做这个方法意味着没有办法做一个绿色的盒子来完全覆盖地图的一部分等等,这有点蹩脚。如果我认为我会告诉你任何其他对你的情况有用的东西。——西蒙·萨里斯 7 小时前

回答by JSdc

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.

我有一个圆形的用户界面设备(绘制在一个普通的 HTML5 画布上,它是一个正方形)。只有圆圈是彩色的,画布的其余部分是透明的,我想点击它。在方形画布的角下,有一个 Kinetic JS 舞台上的形状。

Normallyyou 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:

但是您可以将点击事件发送到 Kinetic 形状,并在该形状内激活事件侦听器,如下所示:

    $( '#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
        };
      }

回答by Олег Всильдеревьев

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.

我认为动态更改 z-index 会更好。如果您需要使用控件,请将其 z-index 设置为高于画布。如果您需要使用画布 - 将它的 z-index 设置为高于控件。如何做到这一点的确切方法取决于您的情况。您可以监听 mousedown/mouseup 事件,或者在某些区域上监听 mousemove。