Saya mencoba membuat menu bilah sisi untuk halaman web seluler. Tujuan saya adalah menggeser bilah samping dari 25% tepi kiri layar.

Sidebar menu drag target

Cara serupa digunakan di Mematerialisasikan kerangka kerja Sidenav

#drag-target digunakan untuk menerima peristiwa seret dan bilah sisi geser keluar. Masalahnya adalah #drag-target mencakup bagian dari konten dan memblokir peristiwa klik/sentuh pada elemen yang mendasarinya.

Saya menggunakan aturan CSS pointer-events: none tetapi ini merusak gesekan pada elemen itu sendiri.

Apakah ada cara untuk melewatkan peristiwa sentuh/klik melalui #drag-target pada semua elemen yang mendasarinya, kecuali geser/seret?

4
zur4ik 26 Januari 2020, 15:08

2 jawaban

Jawaban Terbaik

Karena tidak mungkin menangkap peristiwa dengan pointer-events: none diterapkan, saya berlari ke cara lain dengan menangani peristiwa di seluruh badan dan menggeser bilah samping secara manual.

Setelah berjuang dengan Hammer.js saya datang dengan bilah samping yang berfungsi tetapi menemukan bahwa, Hammer memiliki sedikit bug dengan Pan acara dan terkadang acara memberikan delta yang salah. Jadi saya memutuskan untuk mendengarkan TouchEvents dasar.

Inilah hasilnya jika akan bermanfaat bagi siapa saja: https://codepen.io/pen/xxbNwmX

P.S. Uji dari perangkat yang mendukung Touch atau emulator browser

/**
 * @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
zur4ik 28 Januari 2020, 21:47

Seperti yang saya sebutkan dalam komentar, itu harus bekerja dengan z-index sekarang di sini, dalam contoh saya, Anda dapat membawa drag-target di belakang elemen, dan dalam situasi ini, tindakan tombol dan juga swipe tindakan keduanya bekerja dengan sempurna ! lihat ini, dan bandingkan dengan kode Anda. Dan jangan gunakan pointer-events: none karena menonaktifkan semua fungsi mouse !

$('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>
0
Pedram 27 Januari 2020, 06:27