svelte-scrolling
svelte-scrolling copied to clipboard
why use touchstart to trigger the jump ?
whe using touchdevice, and scrolling down with touch, if we touch the link, it will jump to its anchor. I have mad a custom ScrollTo.ts to trigger the jump only on tap
`import { get } from 'svelte/store' import { elements } from 'svelte-scrolling/dist/store' // Adjust based on your project's structure import { getGlobalOptions } from 'svelte-scrolling/dist/internal/globalOptions' // Same here import type { ScrollToOptions } from 'svelte-scrolling/dist/types/options' // Ensure correct type import import { sanitize, getElement, getPosition } from 'svelte-scrolling/dist/shared/utils' // Copy these utilities if needed import scrolling from 'svelte-scrolling/dist/shared/scrolling' // Copy if necessary
const elementsList = get(elements)
// Handle scrolling
const handle = async (event: Event, options: ScrollToOptions): Promise
const { ref, onDone, onStart } = options
const duration = options.duration!
const offset = options.offset!
const easing = options.easing!
const element = getElement(elementsList, ref)
if (!element) {
throw new Error(`Element reference '${ref}' not found`)
}
const endPosition = getPosition(element)
onStart?.({ element, offset, duration, endPosition })
await scrolling(endPosition, { duration, offset, easing })
onDone?.({ element, offset, duration, endPosition })
}
/**
- Listens for click (touchend) events and scrolls to elements with smooth animation
- @param options - The element reference or global options */
// Custom scrollTo with touchend const customScrollTo = (node: HTMLElement, options: string | ScrollToOptions) => { if (!options) { throw new Error('scrollTo requires options') }
let opts: ScrollToOptions = {
ref: '',
...getGlobalOptions()
}
typeof options === 'string' ? (opts.ref = options) : (opts = Object.assign(opts, options))
opts.ref = sanitize(opts.ref)
if (!opts.ref) {
throw new Error('scrollTo requires a reference')
}
if (node instanceof HTMLAnchorElement) {
node.href = `#${opts.ref}`
}
if (node instanceof HTMLAnchorElement === false) {
node.style.cursor = 'pointer'
}
// Variables to track touch movement
let touchStartX = 0
let touchStartY = 0
const handleTouchStart = (event: TouchEvent) => {
const touch = event.touches[0]
touchStartX = touch.clientX
touchStartY = touch.clientY
}
const handleTouchEnd = (event: TouchEvent) => {
const touch = event.changedTouches[0]
const deltaX = Math.abs(touch.clientX - touchStartX)
const deltaY = Math.abs(touch.clientY - touchStartY)
// Define a small threshold for movement to detect a "tap"
const threshold = 10 // pixels
if (deltaX < threshold && deltaY < threshold) {
// Minimal movement: treat it as a tap
handle(event, opts)
}
}
const handleClick = (event: MouseEvent) => handle(event, opts)
// Attach event listeners
node.addEventListener('click', handleClick, { passive: opts.passive })
node.addEventListener('touchstart', handleTouchStart, { passive: opts.passive })
node.addEventListener('touchend', handleTouchEnd, { passive: opts.passive })
return {
destroy() {
node.removeEventListener('click', handleClick)
node.removeEventListener('touchstart', handleTouchStart)
node.removeEventListener('touchend', handleTouchEnd)
}
}
}
export default customScrollTo
`