parent
							
								
									3375619396
								
							
						
					
					
						commit
						6e5b6a3bdb
					
				|  | @ -39,11 +39,14 @@ const isPullEnd = ref(false); | |||
| const isRefreshing = ref(false); | ||||
| const pullDistance = ref(0); | ||||
| 
 | ||||
| let supportPointerDesktop = false; | ||||
| let startScreenY: number | null = null; | ||||
| 
 | ||||
| const rootEl = useTemplateRef('rootEl'); | ||||
| let scrollEl: HTMLElement | null = null; | ||||
| 
 | ||||
| let disabled = false; | ||||
| 
 | ||||
| const props = withDefaults(defineProps<{ | ||||
| 	refresher: () => Promise<void>; | ||||
| }>(), { | ||||
|  | @ -54,17 +57,17 @@ const emit = defineEmits<{ | |||
| 	(ev: 'refresh'): void; | ||||
| }>(); | ||||
| 
 | ||||
| function moveStart(event: PointerEvent) { | ||||
| 	if (scrollEl!.scrollTop !== 0) return; | ||||
| function getScreenY(event) { | ||||
| 	if (supportPointerDesktop) { | ||||
| 		return event.screenY; | ||||
| 	} | ||||
| 	return event.touches[0].screenY; | ||||
| } | ||||
| 
 | ||||
| 	window.addEventListener('pointermove', moving, { passive: false }); // passive: falseにしないとpreventDefaultが使えない | ||||
| 	// setPointerCaptureするとクリックが効かなくなる | ||||
| 	//rootEl.value.setPointerCapture(event.pointerId); | ||||
| 	window.addEventListener('pointerup', moveEnd, { passive: true, once: true }); | ||||
| 
 | ||||
| 	if (!isPullStart.value && !isRefreshing.value) { | ||||
| function moveStart(event) { | ||||
| 	if (!isPullStart.value && !isRefreshing.value && !disabled) { | ||||
| 		isPullStart.value = true; | ||||
| 		startScreenY = event.screenY; | ||||
| 		startScreenY = getScreenY(event); | ||||
| 		pullDistance.value = 0; | ||||
| 	} | ||||
| } | ||||
|  | @ -105,39 +108,7 @@ async function closeContent() { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| function moving(event: PointerEvent) { | ||||
| 	if (!isPullStart.value || isRefreshing.value) return; | ||||
| 
 | ||||
| 	if ((scrollEl?.scrollTop ?? 0) > SCROLL_STOP + pullDistance.value || isHorizontalSwipeSwiping.value) { | ||||
| 		pullDistance.value = 0; | ||||
| 		isPullEnd.value = false; | ||||
| 		moveEnd(event); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if (startScreenY === null) { | ||||
| 		startScreenY = event.screenY; | ||||
| 	} | ||||
| 	const moveScreenY = event.screenY; | ||||
| 
 | ||||
| 	const moveHeight = moveScreenY - startScreenY!; | ||||
| 	pullDistance.value = Math.min(Math.max(moveHeight, 0), MAX_PULL_DISTANCE); | ||||
| 
 | ||||
| 	if (pullDistance.value > 0) { | ||||
| 		if (event.cancelable) event.preventDefault(); | ||||
| 	} | ||||
| 
 | ||||
| 	if (pullDistance.value > SCROLL_STOP) { | ||||
| 		event.stopPropagation(); | ||||
| 	} | ||||
| 
 | ||||
| 	isPullEnd.value = pullDistance.value >= FIRE_THRESHOLD; | ||||
| } | ||||
| 
 | ||||
| function moveEnd(event: PointerEvent) { | ||||
| 	window.removeEventListener('pointermove', moving); | ||||
| 	//rootEl.value.releasePointerCapture(event.pointerId); | ||||
| 
 | ||||
| function moveEnd() { | ||||
| 	if (isPullStart.value && !isRefreshing.value) { | ||||
| 		startScreenY = null; | ||||
| 		if (isPullEnd.value) { | ||||
|  | @ -155,6 +126,35 @@ function moveEnd(event: PointerEvent) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| function moving(event: TouchEvent | PointerEvent) { | ||||
| 	if (!isPullStart.value || isRefreshing.value || disabled) return; | ||||
| 
 | ||||
| 	if ((scrollEl?.scrollTop ?? 0) > (supportPointerDesktop ? SCROLL_STOP : SCROLL_STOP + pullDistance.value) || isHorizontalSwipeSwiping.value) { | ||||
| 		pullDistance.value = 0; | ||||
| 		isPullEnd.value = false; | ||||
| 		moveEnd(); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if (startScreenY === null) { | ||||
| 		startScreenY = getScreenY(event); | ||||
| 	} | ||||
| 	const moveScreenY = getScreenY(event); | ||||
| 
 | ||||
| 	const moveHeight = moveScreenY - startScreenY!; | ||||
| 	pullDistance.value = Math.min(Math.max(moveHeight, 0), MAX_PULL_DISTANCE); | ||||
| 
 | ||||
| 	if (pullDistance.value > 0) { | ||||
| 		if (event.cancelable) event.preventDefault(); | ||||
| 	} | ||||
| 
 | ||||
| 	if (pullDistance.value > SCROLL_STOP) { | ||||
| 		event.stopPropagation(); | ||||
| 	} | ||||
| 
 | ||||
| 	isPullEnd.value = pullDistance.value >= FIRE_THRESHOLD; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * emit(refresh)が完了したことを知らせる関数 | ||||
|  * | ||||
|  | @ -167,17 +167,35 @@ function refreshFinished() { | |||
| 	}); | ||||
| } | ||||
| 
 | ||||
| function setDisabled(value) { | ||||
| 	disabled = value; | ||||
| } | ||||
| 
 | ||||
| function onScrollContainerScroll() { | ||||
| 	const scrollPos = scrollEl!.scrollTop; | ||||
| 
 | ||||
| 	// When at the top of the page, disable vertical overscroll so passive touch listeners can take over. | ||||
| 	if (scrollPos === 0) { | ||||
| 		scrollEl!.style.touchAction = 'pan-x pan-down pinch-zoom'; | ||||
| 		registerEventListenersForReadyToPull(); | ||||
| 	} else { | ||||
| 		scrollEl!.style.touchAction = 'auto'; | ||||
| 		unregisterEventListenersForReadyToPull(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| function registerEventListenersForReadyToPull() { | ||||
| 	if (rootEl.value == null) return; | ||||
| 	rootEl.value.addEventListener('touchstart', moveStart, { passive: true }); | ||||
| 	rootEl.value.addEventListener('touchmove', moving, { passive: false }); // passive: falseにしないとpreventDefaultが使えない | ||||
| } | ||||
| 
 | ||||
| function unregisterEventListenersForReadyToPull() { | ||||
| 	if (rootEl.value == null) return; | ||||
| 	rootEl.value.removeEventListener('touchstart', moveStart); | ||||
| 	rootEl.value.removeEventListener('touchmove', moving); | ||||
| } | ||||
| 
 | ||||
| onMounted(() => { | ||||
| 	if (rootEl.value == null) return; | ||||
| 
 | ||||
|  | @ -186,11 +204,19 @@ onMounted(() => { | |||
| 
 | ||||
| 	scrollEl.addEventListener('scroll', onScrollContainerScroll, { passive: true }); | ||||
| 
 | ||||
| 	rootEl.value.addEventListener('pointerdown', moveStart, { passive: true }); | ||||
| 	rootEl.value.addEventListener('touchend', moveEnd, { passive: true }); | ||||
| 
 | ||||
| 	registerEventListenersForReadyToPull(); | ||||
| }); | ||||
| 
 | ||||
| onUnmounted(() => { | ||||
| 	if (scrollEl) scrollEl.removeEventListener('scroll', onScrollContainerScroll); | ||||
| 
 | ||||
| 	unregisterEventListenersForReadyToPull(); | ||||
| }); | ||||
| 
 | ||||
| defineExpose({ | ||||
| 	setDisabled, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue