【问题标题】:Allow pointer (click) events to pass through element whilst maintaining scroll facility允许指针(单击)事件通过元素,同时保持滚动功能
【发布时间】:2017-05-26 07:56:28
【问题描述】:

我的目标是拥有一个允许:

  1. 下面要点击/交互的元素,
  2. 滚动

众所周知,1 的解是pointer-events: none。如Click through a DIV to underlying elements 中所述。

但是,该元素无法滚动,因为滚动条出现在带有pointer-events: none 的元素上。这可以在这个例子中看到:http://jsbin.com/madure/2/edit?html,css,output

是否有解决方法,或者是否需要在浏览器级别解决?也许还有一条附加规则,pointer-events: scrollOnly

【问题讨论】:

  • 你可以接受它不阻止鼠标事件的结束/离开,以及像悬停这样的 CSS 状态吗?如果是这样,我可以提供一个纯 CSS 的解决方案,它将阻止父级上的所有单击类型鼠标/指针事件。告诉我,我会发布解决方案。
  • @csuwldcat 对于我的用例,我想要除滚动/鼠标滚轮(或单击滚动条本身)之外的所有指针事件,因此需要悬停。但是,无论如何它可能值得发布,因为它可以帮助其他人。 :-)
  • 你好奥利弗,我面临着和你完全相同的问题。我需要滚动一个 div,但让所有其他事件“通过”到它后面的 div。你的问题解决了吗?谢谢

标签: javascript html css dom


【解决方案1】:

pointer-events CSS 属性指定在什么情况下(如果 任何)特定的图形元素可以成为鼠标的目标 事件。

所以基本上如果你让上层对点击不敏感,那么对于滚轮事件也是如此。我建议两件事

JavaScript 解决方法: 这基本上使用了以下事实:

注意防止元素成为鼠标事件的目标 通过使用指针事件并不一定意味着鼠标事件 该元素上的侦听器不能或不会被触发

	$(function(){
		$("#stage-layer").on("wheel",function(e){
			eo=e.originalEvent;
			s=$("#scrollable")
			switch(eo.deltaMode){
				case 0: 		//DOM_DELTA_PIXEL		Chrome
					s.scrollTop(eo.deltaY+s.scrollTop())
					s.scrollLeft(eo.deltaX+s.scrollLeft())	
					break;
				case 1: 		//DOM_DELTA_LINE		Firefox
					s.scrollTop(15*eo.deltaY+s.scrollTop())	//scroll(e.deltaX, e.deltaY); 	Just a random small amount of scrolling 
					s.scrollLeft(15*eo.deltaX+s.scrollLeft())
					break;
				case 2: 		//DOM_DELTA_PAGE
					s.scrollTop(0.03*eo.deltaY+s.scrollTop())
					s.scrollLeft(0.03*eo.deltaX+s.scrollLeft())
					break;
			}
			e.stopPropagation();
			e.preventDefault()
		})
		
	})
.container {
    position: relative;
    width: 400px;
    height: 400px;
    border: 2px solid black;
}

#stage-layer {
    position: absolute;
    width: 100%;
    box-sizing: border-box;
    height: 100%;
    border: 2px solid yellow;
}

#application-layer {
    position: relative;
    box-sizing: border-box;
    height: 100%;
    border: 2px solid pink;
    pointer-events: none;
}

rect:hover {
    fill: blue;
}

#scrollable {
    overflow: auto;
    color: hotpink;
    height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

    <div class="container">
        <svg id="stage-layer">
            <rect width="200" height="200"></rect>
        </svg>
        <div id="application-layer">
            <div id="scrollable">
                <p>foo1</p>
                <p>foo2</p>
                <p>foo3</p>
                <p>foo4</p>
                <p>foo5</p>
                <p>foo6</p>
            </div>
        </div>
    </div>

一个不错的提示:

这可能不会立即产生解决方案,但它是长期 Web 开发的不错选择:

我们希望 在 HTML 中提供更细粒度的控制(不仅仅是自动和无)... 如果您有任何特别想做的事情 有了这个属性,那么请将它们添加到用例部分 this wiki page(不用担心保持整洁)。

来源:pointer-events

【讨论】:

    【解决方案2】:

    翻译@user10089632 对香草 javascript 的回答

    function scroller(event){
      scrollable=document.getElementById("scrollable");
      switch(event.deltaMode){
        case 0: 		//DOM_DELTA_PIXEL		Chrome
          scrollable.scrollTop+=event.deltaY
          scrollable.scrollLeft+=event.deltaX
          break;
        case 1: 		//DOM_DELTA_LINE		Firefox
          scrollable.scrollTop+=15*event.deltaY
          scrollable.scrollLeft+=15*event.deltaX
          break;
        case 2: 		//DOM_DELTA_PAGE
          scrollable.scrollTop+=0.03*event.deltaY
          scrollable.scrollLeft+=0.03*event.deltaX
          break;
      }
      event.stopPropagation();
      event.preventDefault()
    }
    
    document.onwheel = scroller;
    .container {
        position: relative;
        width: 400px;
        height: 400px;
        border: 2px solid black;
    }
    
    #stage-layer {
        position: absolute;
        width: 100%;
        box-sizing: border-box;
        height: 100%;
        border: 2px solid yellow;
    }
    
    #application-layer {
        position: relative;
        box-sizing: border-box;
        height: 100%;
        border: 2px solid pink;
        pointer-events: none;
    }
    
    rect:hover {
        fill: blue;
    }
    
    #scrollable {
        overflow: auto;
        color: hotpink;
        height: 100px;
    }
    <div class="container">
        <svg id="stage-layer">
            <rect width="200" height="200"></rect>
        </svg>
        <div id="application-layer">
            <div id="scrollable">
                <p>foo1</p>
                <p>foo2</p>
                <p>foo3</p>
                <p>foo4</p>
                <p>foo5</p>
                <p>foo6</p>
            </div>
        </div>
    </div>

    【讨论】:

      猜你喜欢
      • 2021-08-26
      • 2017-03-19
      • 2014-01-13
      • 1970-01-01
      • 1970-01-01
      • 2017-09-10
      • 2019-08-19
      • 2020-06-19
      • 1970-01-01
      相关资源
      最近更新 更多