Как отключить указатель-события, но разрешить перетаскивание - PullRequest
4 голосов
/ 26 января 2020

Я пытаюсь создать боковое меню для мобильной веб-страницы. Моя цель - выдвинуть боковую панель из 25% левого края экрана.

Sidebar menu drag target

Аналогичный способ используется в Материализация каркасов Sidenav

#drag-target используется для получения событий перетаскивания и выдвижной боковой панели. Проблема в том, что #drag-target покрывает часть содержимого и блокирует события нажатия / касания на базовых элементах.

Я использовал CSS rule pointer-events: none, но это нарушает движение по самому элементу.

Есть ли способ передать события касания / щелчка через #drag-target на все базовые элементы, кроме пролистывания / перетаскивания?

Ответы [ 2 ]

0 голосов
/ 29 января 2020

Поскольку невозможно отследить события с применением 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>
0 голосов
/ 26 января 2020

Как я уже упоминал в комментарии, он должен работать с z-index, теперь здесь, в моем примере, вы можете поместить drag-target за элементы, и в этой ситуации действие кнопки, а также действие swipe работают отлично ! проверьте это и сравните с вашим кодом. И не используйте 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...