zur*_*4ik 5 html javascript css jquery materialize
我正在尝试为移动网页创建一个侧边栏菜单。我的目标是从 25% 的屏幕左边缘滑出侧边栏。
Materialise 框架 Sidenav中使用了类似的方式
#drag-target用于接收拖动事件和滑出侧边栏。问题是#drag-target覆盖了部分内容并阻止了底层元素上的点击/触摸事件。
我使用了 CSS 规则pointer-events: none,但这会破坏元素本身的滑动。
除了滑动/拖动之外,有什么方法可以通过#drag-target所有底层元素传递触摸/单击事件?
由于不可能通过pointer-events: none应用捕获事件,因此我采用了另一种方式,即处理整个主体上的事件并手动滑动侧边栏。
经过一番挣扎后,Hammer.js我使用了工作侧边栏,但发现 Hammer 在Pan事件方面有一个小错误,有时事件给出了不正确的增量。所以我决定听基本的TouchEvents。
这是结果,如果它对任何人都有帮助:https://codepen.io/pen/xxbNwmX
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')
})Run Code Online (Sandbox Code Playgroud)
* {
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
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)