+
{#each visiblePhotos as photo, index (photo.id)}
{
+ let startTime: number
+ let startX: number
+ let startY: number
+ let endX: number
+ let endY: number
+
+ if (!node) {
+ throw new Error('No specified node')
+ }
+
+ // Detect swipe direction from given values
+ const detectDirection = (startX: number, startY: number, endX: number, endY: number) => {
+ // If action has been made within the timeframe (after would return)
+ if (Date.now() - startTime < options.timeframe) {
+ const deltaX = endX - startX
+ const deltaY = endY - startY
+ const absX = Math.abs(deltaX)
+ const absY = Math.abs(deltaY)
+
+ // Horizontal
+ if (absX >= 2 * absY && absX > options.travelX) {
+ return deltaX > 0 ? 'x' : '-x'
+ }
+ // Vertical
+ else if (absY >= 2 * absX && absY > options.travelY) {
+ return deltaY > 0 ? 'y' : '-y'
+ }
+ // Tap
+ else return null
+ }
+ }
+
+ // Down event
+ const onDown = ({ x, y }: PointerEvent) => {
+ startX = x
+ startY = y
+ startTime = Date.now()
+ }
+ node.addEventListener('pointerdown', onDown, false)
+
+
+ // Up event
+ const onUp = ({ x, y }: PointerEvent) => {
+ endX = x
+ endY = y
+
+ // Get direction from values
+ const direction = detectDirection(startX, startY, endX, endY)
+ if (direction) {
+ // Dispatch event if direction has been detected
+ node.dispatchEvent(
+ new CustomEvent('swipe', { detail: direction })
+ )
+ }
+ }
+ node.addEventListener('pointerup', onUp, false)
+
+
+ return {
+ /**
+ * Destroy
+ */
+ destroy () {
+ node.removeEventListener('pointerdown', onDown)
+ node.removeEventListener('pointerup', onUp)
+ }
+ }
+}
+
+
+/**
+ * Types
+ */
+interface SwipeOptions {
+ travelX?: number
+ travelY?: number
+ timeframe?: number
+}
\ No newline at end of file