1857

我有一个divbackground:transparent还有border。在这之下div,我有更多的元素。

目前,当我点击覆盖层之外时,我可以点击底层元素div。但是,直接单击覆盖时,我无法单击基础元素div

我希望能够点击它div,以便我可以点击底层元素。

我的问题

4

17 回答 17

2991

是的,你可以这样做。

与 IE11 的 CSS 条件语句一起使用pointer-events: none(在 IE10 或更低版本中不起作用),您可以获得针对此问题的跨浏览器兼容的解决方案。

使用AlphaImageLoader,您甚至可以将透明.PNG/.GIFs 放在叠加层中div,并让点击流到下面的元素。

CSS:

pointer-events: none;
background: url('your_transparent.png');

IE11 条件:

filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='your_transparent.png', sizingMethod='scale');
background: none !important;

这是一个包含所有代码的基本示例页面。

于 2011-01-29T21:49:17.727 回答
436

是的,您可以强制重叠图层通过(忽略)点击事件。
另外,您可以将特定儿童排除在此行为之外...

你可以这样做,使用pointer-events

pointer-events影响对单击、点击、滚动和悬停事件的反应。


在应该忽略/传递您设置的提到的事件的层中

pointer-events: none; 

需要再次对鼠标/点击事件做出反应的无响应层的子级需要:

pointer-events: auto; 

如果您使用多个重叠的 div 层(可能某些父级是透明的),那么第二部分非常有用,您需要能够单击子元素并且仅单击该子元素。

示例用法:

.parent {
  pointer-events:none;        
}
.child {
  pointer-events:auto;
}
<div class="parent">
  <a href="#">I'm unresponsive</a>
  <a href="#" class="child">I'm clickable again, wohoo !</a>
</div>

于 2014-11-07T11:06:36.277 回答
47

允许用户点击div到底层元素取决于浏览器。所有现代浏览器,包括 Firefox、Chrome、Safari 和 Opera,都理解pointer-events:none.

对于 IE,这取决于背景。如果背景是透明的,则无需您执行任何操作即可点击通过。另一方面,对于类似的background:white; opacity:0; filter:Alpha(opacity=0);,IE 需要手动事件转发。

请参阅JSFiddle 测试CanIUse 指针事件

于 2012-10-16T17:26:18.107 回答
21

我正在添加这个答案,因为我没有在这里完整地看到它。我能够使用 elementFromPoint 做到这一点。所以基本上:

  • 将单击附加到要单击的 div
  • 把它藏起来
  • 确定指针在哪个元素上
  • 点击那里的元素。
var range-selector= $("")
    .css("position", "absolute").addClass("range-selector")
    .appendTo("")
    .click(function(e) {
        _range-selector.hide();

        $(document.elementFromPoint(e.clientX,e.clientY)).trigger("click");
    });

在我的例子中,覆盖的 div 是绝对定位的——我不确定这是否会有所作为。这至少适用于 IE8/9、Safari Chrome 和 Firefox。

于 2012-05-16T17:25:05.273 回答
17
  1. 隐藏覆盖元素
  2. 确定光标坐标
  3. 在这些坐标上获取元素
  4. 触发点击元素
  5. 再次显示覆盖元素
$('#elementontop').click(e => {
    $('#elementontop').hide();
    $(document.elementFromPoint(e.clientX, e.clientY)).trigger("click");
    $('#elementontop').show();
});
于 2013-02-20T20:04:55.283 回答
12

我需要这样做并决定采取这条路线:

$('.overlay').click(function(e){
    var left = $(window).scrollLeft();
    var top = $(window).scrollTop();

    //hide the overlay for now so the document can find the underlying elements
    $(this).css('display','none');
    //use the current scroll position to deduct from the click position
    $(document.elementFromPoint(e.pageX-left, e.pageY-top)).click();
    //show the overlay again
    $(this).css('display','block');
});
于 2012-07-11T19:29:49.883 回答
6

我目前使用帆布语音气球。但是由于带有指针的气球被包裹在一个div中,它下面的一些链接不再可以点击了。在这种情况下我不能使用 extjs。 请参阅我的语音气球教程 需要 HTML5的基本示例

所以我决定从一个数组中的气球内部收集所有链接坐标。

var clickarray=[];
function getcoo(thatdiv){
         thatdiv.find(".link").each(function(){
                 var offset=$(this).offset();           
                 clickarray.unshift([(offset.left),
                                     (offset.top),
                                     (offset.left+$(this).width()),
                                     (offset.top+$(this).height()),
                                     ($(this).attr('name')),
                                     1]);
                                     });
         }

我在每个(新)气球上调用这个函数。它获取link.class的左/上角和右/下角的坐标 - 另外,如果有人点击该坐标,我喜欢设置一个1,这意味着它没有被点击jet . 并将此数组移至 clickarray。你也可以使用推。

要使用该数组:

$("body").click(function(event){
          event.preventDefault();//if it is a a-tag
          var x=event.pageX;
          var y=event.pageY;
          var job="";
          for(var i in clickarray){
              if(x>=clickarray[i][0] && x<=clickarray[i][2] && y>=clickarray[i][1] && y<=clickarray[i][3] && clickarray[i][5]==1){
                 job=clickarray[i][4];
                 clickarray[i][5]=0;//set to allready clicked
                 break;
                }
             }
          if(job.length>0){   
             // --do some thing with the job --
            }
          });

这个函数证明一个body点击事件的坐标或者它是否已经被点击并返回name属性。我认为没有必要更深入,但你看它并没有那么复杂。希望是英语...

于 2012-01-09T13:36:01.720 回答
5

(根据情况)尝试的另一个想法是:

  1. 将你想要的内容放在一个div中;
  2. 将非点击叠加层放在整个页面上,z-index 更高,
  3. 制作原始 div 的另一个裁剪副本
  4. overlay 和 abs 将复制 div 放置在与您希望使用更高 z-index 可点击的原始内容相同的位置?

有什么想法吗?

于 2013-02-26T22:32:42.013 回答
3

不,您不能单击“通过”元素。您可以获取单击的坐标并尝试找出单击元素下方的元素,但这对于没有document.elementFromPoint. 然后,您仍然必须模拟默认的单击操作,这不一定是微不足道的,具体取决于您在那里拥有的元素。

由于您有一个完全透明的窗口区域,您最好将其实现为围绕外部的单独边框元素,使中心区域没有障碍物,这样您就可以直接点击。

于 2010-09-09T21:27:16.160 回答
3

只需将a标签包裹在所有 HTML 提取中,例如

<a href="/categories/1">
  <img alt="test1" class="img-responsive" src="/assets/photo.jpg" />
  <div class="caption bg-orange">
    <h2>
      test1
    </h2>
  </div>
</a>

在我的示例中,我的标题类具有悬停效果,带有指针事件:无;你只会输

包装内容将保留您的悬停效果,您可以单击所有图片,包括 div,问候!

于 2014-02-16T21:28:30.767 回答
3

一种更简单的方法是使用 Data URI 内联透明背景图像,如下所示:

.click-through {
    pointer-events: none;
    background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);
}
于 2019-05-25T21:40:43.103 回答
2

我认为您可以考虑更改标记。如果我没记错的话,您想在文档上方放置一个不可见层,并且您的不可见标记可能位于文档图像之前(这是正确的吗?)。

相反,我建议您将不可见的位置放在文档图像之后,但将位置更改为绝对位置。

请注意,您需要一个父元素具有 position: relative ,然后您将能够使用这个想法。否则你的绝对层将被放置在左上角。

绝对位置元素相对于第一个具有非静态位置的父元素定位。如果没有找到这样的元素,则包含块是 html

希望这可以帮助。有关 CSS 定位的更多信息,请参见此处

于 2011-07-28T21:00:05.087 回答
2

我认为event.stopPropagation();这里也应该提到。将此添加到按钮的单击功能中。

防止事件在 DOM 树中冒泡,防止任何父处理程序收到事件通知。

于 2018-06-14T12:10:27.273 回答
1

它不是那样工作的。解决方法是手动检查鼠标点击的坐标与每个元素占用的区域。

元素占据的区域可以通过以下方式找到: 1. 获取元素相对于页面左上角的位置,以及 2. 宽度和高度。像 jQuery 这样的库使这变得非常简单,尽管它可以在纯 js 中完成。mousemove在对象上添加事件处理程序document将提供从页面顶部和左侧连续更新鼠标位置。决定鼠标是否在任何给定对象上包括检查鼠标位置是否在元素的左、右、上和下边缘之间。

于 2010-09-09T20:45:19.487 回答
1

您可以放置​​一个 AP 覆盖,如...

#overlay {
  position: absolute;
  top: -79px;
  left: -60px;
  height: 80px;
  width: 380px;
  z-index: 2;
  background: url(fake.gif);
}
<div id="overlay"></div>

把它放在你不想要的地方,即点击。在所有工作。

于 2012-10-29T17:09:05.913 回答
1

这不是该问题的准确答案,但可能有助于找到解决方法。

我有一个图像,我在页面加载时隐藏并在等待 AJAX 调用时显示,然后再次隐藏......

我发现在加载页面时显示我的图像然后使其消失并能够在隐藏图像之前单击图像所在位置的唯一方法是将图像放入 DIV 中,使 DIV 的大小为 10x10 像素或更小足以防止它引起问题,然后隐藏包含的 div。这允许图像在可见时溢出 div,当 div 被隐藏时,只有 div 区域受到无法单击下方对象的影响,而不是 DIV 包含和显示的图像的整个大小。

我尝试了所有隐藏图像的方法,包括 CSS display=none/block、opacity=0、用 hidden=true 隐藏图像。所有这些都导致我的图像被隐藏,但它显示的区域就像下面的东西有一个覆盖物一样,因此点击等不会作用于底层对象。一旦图像在一个小 DIV 内并且我隐藏了这个小 DIV,图像占据的整个区域都很清晰,只有我隐藏的 DIV 下的小区域受到影响,但是当我让它足够小(10x10 像素)时,问题是固定的(有点)。

对于应该是一个简单问题的问题,我发现这是一个肮脏的解决方法,但我无法找到任何方法在没有容器的情况下以本机格式隐藏对象。我的对象是等的形式。如果有人有更好的方法,请告诉我。

于 2019-08-09T14:25:40.380 回答
1

我不能总是在我的场景中使用pointer-events: none,因为我希望覆盖层底层元素都是可点击/可选择的。

DOM 结构如下所示:

<div id="outerElement">
   <div id="canvas-wrapper">
      <canvas id="overlay"></canvas>
   </div>
   <!-- Omitted: element(s) behind canvas that should still be selectable -->
</div>

outerElement,canvas-wrappercanvas元素具有相同的大小。)

为了使画布后面的元素正常运行(例如可选择、可编辑),我使用了以下代码:

canvasWrapper.style.pointerEvents = 'none';

outerElement.addEventListener('mousedown', event => {
    const clickedOnElementInCanvas = yourCheck // TODO: check if the event *would* click a canvas element.
    if (!clickedOnElementInCanvas) {

        // if necessary, add logic to deselect your canvas elements ...

        wrapper.style.pointerEvents = 'none';
        return true;
    }

    // Check if we emitted the event ourselves (avoid endless loop)
    if (event.isTrusted) {
        // Manually forward element to the canvas
        const mouseEvent = new MouseEvent(event.type, event);
        canvas.dispatchEvent(mouseEvent);
        mouseEvent.stopPropagation();
    }
    return true;
});

一些画布对象还带有输入字段,所以我也必须允许键盘事件。为此,我必须pointerEvents根据画布输入字段当前是否聚焦来更新属性:

onCanvasModified(canvas, () => {
    const inputFieldInCanvasActive = // TODO: Check if an input field of the canvas is active.
    wrapper.style.pointerEvents = inputFieldInCanvasActive  ? 'auto' : 'none';
});
于 2021-01-13T18:39:29.290 回答