feat: image pinch to zoom (#1620)

This commit is contained in:
Tuur Martens 2023-02-04 19:05:55 +01:00 committed by GitHub
parent e92d1c6adf
commit 2cf8f591e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,5 +1,7 @@
<script setup lang="ts">
import { SwipeDirection } from '@vueuse/core'
import { useGesture } from '@vueuse/gesture'
import type { PermissiveMotionProperties } from '@vueuse/motion'
import { useReducedMotion } from '@vueuse/motion'
import type { mastodon } from 'masto'
@ -23,18 +25,36 @@ const reduceMotion = useReducedMotion()
const canAnimate = computed(() => !reduceMotion.value && animateTimeout.value)
const { motionProperties } = useMotionProperties(target, {
cursor: 'grab',
scale: 1,
x: 0,
y: 0,
})
const { set } = useSpring(motionProperties as Partial<PermissiveMotionProperties>)
function resetZoom() {
set({ scale: 1 })
}
watch(modelValue, resetZoom)
const { width, height } = useElementSize(target)
const { isSwiping, lengthX, lengthY, direction } = useSwipe(target, {
threshold: 5,
passive: false,
onSwipeEnd(e, direction) {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
if (direction === SwipeDirection.RIGHT && Math.abs(distanceX.value) > threshold)
if (direction === SwipeDirection.RIGHT && Math.abs(distanceX.value) > threshold) {
modelValue.value = Math.max(0, modelValue.value - 1)
resetZoom()
}
// eslint-disable-next-line @typescript-eslint/no-use-before-define
if (direction === SwipeDirection.LEFT && Math.abs(distanceX.value) > threshold)
if (direction === SwipeDirection.LEFT && Math.abs(distanceX.value) > threshold) {
modelValue.value = Math.min(media.length - 1, modelValue.value + 1)
resetZoom()
}
// eslint-disable-next-line @typescript-eslint/no-use-before-define
if (direction === SwipeDirection.UP && Math.abs(distanceY.value) > threshold)
@ -42,6 +62,21 @@ const { isSwiping, lengthX, lengthY, direction } = useSwipe(target, {
},
})
useGesture({
onPinch({ offset: [distance, angle] }) {
set({ scale: 1 + distance / 200 })
},
onMove({ movement: [x, y], dragging, pinching }) {
if (dragging && !pinching)
set({ x, y })
},
}, {
domTarget: target,
eventOptions: {
passive: true,
},
})
const distanceX = computed(() => {
if (width.value === 0)
return 0