简体   繁体   English

如何禁用指针事件,但允许拖动

[英]How to disable pointer-events, but allow drag

I'm trying to create a sidebar menu for the mobile web page.我正在尝试为移动网页创建侧边栏菜单。 My goal is to slide-out side-bar from 25% of screens left edge.我的目标是从 25% 的屏幕左边缘滑出侧边栏。

侧边栏菜单拖动目标

A similar way is used in Materialize frameworks SidenavMaterialise 框架 Sidenav 中使用了类似的方式

#drag-target is used to receive drag events and slide-out sidebar. #drag-target用于接收拖动事件和滑出侧边栏。 Problem is that #drag-target covers part of the content and blocks click/touch events on underlying elements.问题是#drag-target覆盖了部分内容并阻止了底层元素上的点击/触摸事件。

I used CSS rule pointer-events: none but this breaks swipe on the element itself.我使用了 CSS rule pointer-events: none但这会破坏元素本身的滑动。

Is there any way to pass touch/click events through the #drag-target on all underlying elements, except swipe/drag?除了滑动/拖动之外,有没有办法通过所有底层元素上的#drag-target传递触摸/点击事件?

As I mentioned in comment, it should work with z-index now here, in my example, you can bring drag-target behind the elements, and in this situation, button action and also swipe action both works perfectly !正如我在评论中提到的,它现在应该与z-index一起使用,在我的示例中,您可以将drag-target放在元素后面,在这种情况下,按钮操作和swipe操作都可以完美运行 check this out, and compare with your code.检查一下,并与您的代码进行比较。 And do not use pointer-events: none becuase it disable all mouse functions !并且不要使用pointer-events: none因为它会禁用所有鼠标功能

 $('button').click(function() { alert('button action!') }); var myElement = document.getElementById('drag-target'); var Hammer = new Hammer(myElement); Hammer.on("swipe", function(ev) { console.log(ev.type) alert('come out and play!') });
 #drag-target { width: 25%; height: 100%; background: transparent; position: fixed; top: 0; left: 0; border-right: 1px solid #d4d4d4; z-index: -1; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.js" integrity="sha256-GMd3rFxMDNnM5JQEpiKLLl8kSrDuG5egqchk758z59g=" crossorigin="anonymous"></script> <div id="content"> <p>Lorem</p> <button>Button</button> <div id="drag-target"></div> </div>

As it's not possible to catch events with pointer-events: none applied, I ran to another way by handling events on the whole body and manually sliding side-bar.由于无法使用pointer-events: none捕获事件pointer-events: none应用,我通过处理整个身体上的事件并手动滑动侧栏跑到另一种方式。

After struggling with Hammer.js I came with working side-bar but found out that, Hammer has a little bug with Pan events and sometimes event was giving incorrect delta.在与Hammer.js苦苦挣扎之后,我使用了侧边栏,但发现,Hammer 在Pan事件方面有一个小错误,有时事件会给出不正确的增量。 So I decided to listen to basic TouchEvents .所以我决定听基本的TouchEvents

Here is the result if it will be helpful to anyone: https://codepen.io/pen/xxbNwmX如果对任何人都有帮助,这是结果: https : //codepen.io/pen/xxbNwmX

PS Test it from Touch-enabled devices or browser emulator PS 从支持触控的设备或浏览器模拟器测试它

 /** * @class Sidenav * @constructor */ class Sidenav { /** * @param wrapper {String | jQuery} * @param sidenav {String | jQuery} * @param [hitArea] {number} * @param [threshold] {number} */ constructor (wrapper, sidenav, hitArea = .20, threshold = 20) { // settings this.wrapper = wrapper this.sidenav = sidenav this.hitArea = window.innerWidth * hitArea this.threshold = threshold this.width = $(sidenav).width() this.isHitarea = false this._state = 'closed' this.states = 'open closed open-started close-started' this.touchStart = 0 // touch start $(this.wrapper).on('touchstart', (e) => { let touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0] this.touchStart = touch.pageX this.isHitarea = this.touchStart < this.hitArea }) // touch move $(this.wrapper).on('touchmove', (e) => { let touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0] let delta = touch.pageX - this.touchStart this.slide(delta) }) // touch end $(this.wrapper).on('touchend', (e) => { let touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0] let delta = touch.pageX - this.touchStart if (this.state == 'open-started') { this.state = Math.abs(delta) >= this.width / 4 ? 'open' : 'closed' } else if (this.state == 'close-started') { this.state = Math.abs(delta) >= this.width / 4 ? 'closed' : 'open' } }) } /** @param st {String} */ set state (st) { this._state = st // remove all classes $(this.wrapper).removeClass(this.states).addClass(st) } get state () { return this._state } slide (delta) { switch (this.state) { case 'closed': if (this.isHitarea && delta >= this.threshold) { this.state = 'open-started' this.move(delta - this.threshold) } break case 'open-started': this.move(delta - this.threshold) break case 'open': if (delta < 0 && Math.abs(delta) > this.threshold) { this.state = 'close-started' let translate = Math.max(-this.width, delta + this.threshold) this.move(translate, 1) } break case 'close-started': let translate = Math.min(Math.max(-this.width, delta + this.threshold), 0) this.move(translate, 1) break } } move (delta, left = false) { if (left) { $(this.wrapper).css('transform', `translateX(${delta}px)`) } else { $(this.wrapper).css('transform', `translateX(${Math.min(-this.width + delta, 0)}px)`) } } } // run $(function() { let sidenav = new Sidenav('.wrapper', '.sidenav') })
 * { margin: 0; padding: 0 } html,body { width: 100%; height: 100%; overflow: hidden } body { background-color: #202126; font-family: Consolas, sans-serif; color: antiquewhite } .wrapper { position: relative; height: 100%; touch-action: pan-x !important; transform: translateX(-240px) } .wrapper .sidenav { position: fixed; left: 0; top: 0; width: 240px; height: 100%; background-color: antiquewhite; color: #202126; box-sizing: border-box; padding: 10px } .wrapper .content { height: 100%; transform: translateX(240px); padding: 10px; overflow-y: scroll; overflow-x: hidden } .wrapper .content button { padding: 10px } .wrapper.open { transform: translateX(0) !important; transition: transform .2s ease-in-out } .wrapper.closed { transform: translateX(-240px) !important; transition: transform .2s ease-in-out }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="wrapper closed"> <div class="sidenav"> <h2>SIDENAV</h2> </div> <div class="content"> <h2>CONTENT</h2> <p>lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet lorem ipsum dolor sit amet</p> <br> <button onclick="alert('Click click!')">Clickable button</button> <br> <br> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus assumenda consequatur debitis doloribus, dolorum esse incidunt nobis obcaecati omnis possimus quasi, quidem recusandae reiciendis rerum tempora unde velit vitae voluptates.</p> <br> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus assumenda consequatur debitis doloribus, dolorum esse incidunt nobis obcaecati omnis possimus quasi, quidem recusandae reiciendis rerum tempora unde velit vitae voluptates.</p> <br> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus assumenda consequatur debitis doloribus, dolorum esse incidunt nobis obcaecati omnis possimus quasi, quidem recusandae reiciendis rerum tempora unde velit vitae voluptates.</p> <br> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus assumenda consequatur debitis doloribus, dolorum esse incidunt nobis obcaecati omnis possimus quasi, quidem recusandae reiciendis rerum tempora unde velit vitae voluptates.</p> <br> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus assumenda consequatur debitis doloribus, dolorum esse incidunt nobis obcaecati omnis possimus quasi, quidem recusandae reiciendis rerum tempora unde velit vitae voluptates.</p> <br> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus assumenda consequatur debitis doloribus, dolorum esse incidunt nobis obcaecati omnis possimus quasi, quidem recusandae reiciendis rerum tempora unde velit vitae voluptates.</p> <br> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus assumenda consequatur debitis doloribus, dolorum esse incidunt nobis obcaecati omnis possimus quasi, quidem recusandae reiciendis rerum tempora unde velit vitae voluptates.</p> <br> </div> </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM