【问题标题】:Click through div to underlying elements点击 div 到底层元素
【发布时间】:2010-09-09 20:42:54
【问题描述】:

我有一个div,它有background:transparent,还有border。在这个div下面,我还有更多的元素。

目前,当我在覆盖div 之外单击时,我能够单击基础元素。但是,直接单击覆盖div 时,我无法单击基础元素。

我希望能够点击这个div,这样我就可以点击底层元素。

【问题讨论】:

    标签: css click mouseevent layer


    【解决方案1】:

    是的,您可以这样做。

    使用pointer-events: none 和 IE11 的 CSS 条件语句(不适用于 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;
    

    这里有一个basic example page 包含所有代码。

    【讨论】:

    • IE11 完全支持指针事件。这意味着所有现代浏览器都支持它。截至 2014 年底,这是一个可行的解决方案。caniuse.com/#search=pointer-events
    【解决方案2】:

    是的,您可以强制重叠图层通过(忽略)点击事件。
    PLUS可以排除特定子级从这种行为...

    你可以这样做,使用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>

    【讨论】:

    【解决方案3】:

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

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

    参见a JSFiddle testCanIUse pointer events

    【讨论】:

    • Safari 中的同样问题。如果底层 div 的背景不透明,则指针事件是错误的。
    【解决方案4】:
    1. 隐藏覆盖元素
    2. 确定光标坐标
    3. 获取这些坐标上的元素
    4. 触发点击元素
    5. 再次显示叠加元素
    $('#elementontop').click(e => {
        $('#elementontop').hide();
        $(document.elementFromPoint(e.clientX, e.clientY)).trigger("click");
        $('#elementontop').show();
    });
    

    【讨论】:

      【解决方案5】:

      我添加这个答案是因为我没有在这里看到完整的答案。我能够使用 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。

      【讨论】:

        【解决方案6】:

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

        .click-through {
            pointer-events: none;
            background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);
        }
        

        【讨论】:

          【解决方案7】:

          我需要这样做,并决定走这条路:

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

          【讨论】:

            【解决方案8】:

            我认为这里也应该提到event.stopPropagation();。将此添加到按钮的 Click 函数中。

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

            【讨论】:

              【解决方案9】:

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

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

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

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

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

              【讨论】:

                【解决方案10】:

                我不能总是在我的场景中使用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>
                

                outerElementcanvas-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';
                });
                

                【讨论】:

                • 明确一点,这里的“canvas”与HTML5无关&lt;canvas&gt;,对吧?
                【解决方案11】:

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

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

                有什么想法吗?

                【讨论】:

                  【解决方案12】:

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

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

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

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

                  希望这会有所帮助。有关 CSS 定位的更多信息,请参阅here

                  【讨论】:

                    【解决方案13】:

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

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

                    把它放在你不想点击的地方。通用。

                    【讨论】:

                      【解决方案14】:

                      例如,只需将 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>
                      

                      在我的示例中,我的标题类具有悬停效果,使用 pointer-events:none; 你只会失去

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

                      【讨论】:

                        【解决方案15】:

                        我目前使用画布语音气球。但是由于带有指针的气球被包裹在一个div中,它下面的一些链接不再可以点击了。在这种情况下我不能使用 extjs。 See basic example for my speech balloon tutorial 需要 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。你也可以使用 push。

                        使用该数组:

                        $("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属性。我认为没有必要更深入,但你看它并没有那么复杂。 希望是英语...

                        【讨论】:

                          【解决方案16】:

                          不,您不能点击“通过”元素。您可以获取点击的坐标并尝试找出点击元素下方的元素,但这对于没有document.elementFromPoint 的浏览器来说确实很乏味。然后你仍然需要模拟点击的默认动作,这并不一定是微不足道的,具体取决于你在那里有什么元素。

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

                          【讨论】:

                            【解决方案17】:

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

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

                            【讨论】:

                            • 如上所述,您可以在透明容器上使用 CSS {pointer-events:none;} 实现此目的。
                            猜你喜欢
                            • 2011-04-10
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多