Поскольку невозможно отследить события с применением pointer-events: none
, я побежал другим путем, обрабатывая события на всем теле и вручную сдвигая боковую панель.
После борьбы с Hammer.js
я пришел с рабочей боковой панелью, но обнаружил, что у Hammer есть небольшая ошибка с событиями Pan
, и иногда событие дает неверную дельту. Поэтому я решил послушать basi c 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')
})
* {
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>