routie dev init since i didn't adhere to any proper guidance up until now
This commit is contained in:
+140
@@ -0,0 +1,140 @@
|
||||
// Composables
|
||||
import { useToggleScope } from "../../composables/toggleScope.js";
|
||||
import { useVelocity } from "../../composables/touch.js"; // Utilities
|
||||
import { computed, onBeforeUnmount, onMounted, onScopeDispose, shallowRef, watchEffect } from 'vue';
|
||||
import { clamp } from "../../util/index.js"; // Types
|
||||
export function useTouch({
|
||||
el,
|
||||
isActive,
|
||||
isTemporary,
|
||||
width,
|
||||
touchless,
|
||||
position
|
||||
}) {
|
||||
onMounted(() => {
|
||||
window.addEventListener('touchstart', onTouchstart, {
|
||||
passive: true
|
||||
});
|
||||
window.addEventListener('touchmove', onTouchmove, {
|
||||
passive: false
|
||||
});
|
||||
window.addEventListener('touchend', onTouchend, {
|
||||
passive: true
|
||||
});
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('touchstart', onTouchstart);
|
||||
window.removeEventListener('touchmove', onTouchmove);
|
||||
window.removeEventListener('touchend', onTouchend);
|
||||
});
|
||||
const isHorizontal = computed(() => ['left', 'right'].includes(position.value));
|
||||
const {
|
||||
addMovement,
|
||||
endTouch,
|
||||
getVelocity
|
||||
} = useVelocity();
|
||||
let maybeDragging = false;
|
||||
const isDragging = shallowRef(false);
|
||||
const dragProgress = shallowRef(0);
|
||||
const offset = shallowRef(0);
|
||||
let start;
|
||||
function getOffset(pos, active) {
|
||||
return (position.value === 'left' ? pos : position.value === 'right' ? document.documentElement.clientWidth - pos : position.value === 'top' ? pos : position.value === 'bottom' ? document.documentElement.clientHeight - pos : oops()) - (active ? width.value : 0);
|
||||
}
|
||||
function getProgress(pos, limit = true) {
|
||||
const progress = position.value === 'left' ? (pos - offset.value) / width.value : position.value === 'right' ? (document.documentElement.clientWidth - pos - offset.value) / width.value : position.value === 'top' ? (pos - offset.value) / width.value : position.value === 'bottom' ? (document.documentElement.clientHeight - pos - offset.value) / width.value : oops();
|
||||
return limit ? clamp(progress) : progress;
|
||||
}
|
||||
function onTouchstart(e) {
|
||||
if (touchless.value) return;
|
||||
const touchX = e.changedTouches[0].clientX;
|
||||
const touchY = e.changedTouches[0].clientY;
|
||||
const touchZone = 25;
|
||||
const inTouchZone = position.value === 'left' ? touchX < touchZone : position.value === 'right' ? touchX > document.documentElement.clientWidth - touchZone : position.value === 'top' ? touchY < touchZone : position.value === 'bottom' ? touchY > document.documentElement.clientHeight - touchZone : oops();
|
||||
const inElement = isActive.value && (position.value === 'left' ? touchX < width.value : position.value === 'right' ? touchX > document.documentElement.clientWidth - width.value : position.value === 'top' ? touchY < width.value : position.value === 'bottom' ? touchY > document.documentElement.clientHeight - width.value : oops());
|
||||
if (inTouchZone || inElement || isActive.value && isTemporary.value) {
|
||||
start = [touchX, touchY];
|
||||
offset.value = getOffset(isHorizontal.value ? touchX : touchY, isActive.value);
|
||||
dragProgress.value = getProgress(isHorizontal.value ? touchX : touchY);
|
||||
maybeDragging = offset.value > -20 && offset.value < 80;
|
||||
endTouch(e);
|
||||
addMovement(e);
|
||||
}
|
||||
}
|
||||
function onTouchmove(e) {
|
||||
const touchX = e.changedTouches[0].clientX;
|
||||
const touchY = e.changedTouches[0].clientY;
|
||||
if (maybeDragging) {
|
||||
if (!e.cancelable) {
|
||||
maybeDragging = false;
|
||||
return;
|
||||
}
|
||||
const dx = Math.abs(touchX - start[0]);
|
||||
const dy = Math.abs(touchY - start[1]);
|
||||
const thresholdMet = isHorizontal.value ? dx > dy && dx > 3 : dy > dx && dy > 3;
|
||||
if (thresholdMet) {
|
||||
isDragging.value = true;
|
||||
maybeDragging = false;
|
||||
} else if ((isHorizontal.value ? dy : dx) > 3) {
|
||||
maybeDragging = false;
|
||||
}
|
||||
}
|
||||
if (!isDragging.value) return;
|
||||
e.preventDefault();
|
||||
addMovement(e);
|
||||
const progress = getProgress(isHorizontal.value ? touchX : touchY, false);
|
||||
dragProgress.value = Math.max(0, Math.min(1, progress));
|
||||
if (progress > 1) {
|
||||
offset.value = getOffset(isHorizontal.value ? touchX : touchY, true);
|
||||
} else if (progress < 0) {
|
||||
offset.value = getOffset(isHorizontal.value ? touchX : touchY, false);
|
||||
}
|
||||
}
|
||||
function onTouchend(e) {
|
||||
maybeDragging = false;
|
||||
if (!isDragging.value) return;
|
||||
addMovement(e);
|
||||
isDragging.value = false;
|
||||
const velocity = getVelocity(e.changedTouches[0].identifier);
|
||||
const vx = Math.abs(velocity.x);
|
||||
const vy = Math.abs(velocity.y);
|
||||
const thresholdMet = isHorizontal.value ? vx > vy && vx > 400 : vy > vx && vy > 3;
|
||||
if (thresholdMet) {
|
||||
isActive.value = velocity.direction === ({
|
||||
left: 'right',
|
||||
right: 'left',
|
||||
top: 'down',
|
||||
bottom: 'up'
|
||||
}[position.value] || oops());
|
||||
} else {
|
||||
isActive.value = dragProgress.value > 0.5;
|
||||
}
|
||||
}
|
||||
const dragStyles = computed(() => {
|
||||
return isDragging.value ? {
|
||||
transform: position.value === 'left' ? `translateX(calc(-100% + ${dragProgress.value * width.value}px))` : position.value === 'right' ? `translateX(calc(100% - ${dragProgress.value * width.value}px))` : position.value === 'top' ? `translateY(calc(-100% + ${dragProgress.value * width.value}px))` : position.value === 'bottom' ? `translateY(calc(100% - ${dragProgress.value * width.value}px))` : oops(),
|
||||
transition: 'none'
|
||||
} : undefined;
|
||||
});
|
||||
useToggleScope(isDragging, () => {
|
||||
const transform = el.value?.style.transform ?? null;
|
||||
const transition = el.value?.style.transition ?? null;
|
||||
watchEffect(() => {
|
||||
el.value?.style.setProperty('transform', dragStyles.value?.transform || 'none');
|
||||
el.value?.style.setProperty('transition', dragStyles.value?.transition || null);
|
||||
});
|
||||
onScopeDispose(() => {
|
||||
el.value?.style.setProperty('transform', transform);
|
||||
el.value?.style.setProperty('transition', transition);
|
||||
});
|
||||
});
|
||||
return {
|
||||
isDragging,
|
||||
dragProgress,
|
||||
dragStyles
|
||||
};
|
||||
}
|
||||
function oops() {
|
||||
throw new Error();
|
||||
}
|
||||
//# sourceMappingURL=touch.js.map
|
||||
Reference in New Issue
Block a user