Skip to content

Commit

Permalink
feat(ImagePreview): use the touched point as the center of zooming (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
inottn authored May 14, 2023
1 parent 127b5b2 commit d05972d
Showing 1 changed file with 42 additions and 14 deletions.
56 changes: 42 additions & 14 deletions packages/vant/src/image-preview/ImagePreviewItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {

// Composables
import { useTouch } from '../composables/use-touch';
import { useEventListener } from '@vant/use';
import { useEventListener, useRect } from '@vant/use';

// Components
import { Image } from '../image';
Expand All @@ -33,6 +33,11 @@ const getDistance = (touches: TouchList) =>
(touches[0].clientY - touches[1].clientY) ** 2
);

const getCenter = (touches: TouchList) => ({
x: (touches[0].clientX + touches[1].clientX) / 2,
y: (touches[0].clientY + touches[1].clientY) / 2,
});

const bem = createNamespace('image-preview')[1];

export default defineComponent({
Expand Down Expand Up @@ -62,6 +67,7 @@ export default defineComponent({
});

const touch = useTouch();
const imageRef = ref<ComponentInstance>();
const swipeItem = ref<ComponentInstance>();

const vertical = computed(() => {
Expand All @@ -77,9 +83,8 @@ export default defineComponent({
};

if (scale !== 1) {
const offsetX = moveX / scale;
const offsetY = moveY / scale;
style.transform = `scale(${scale}, ${scale}) translate(${offsetX}px, ${offsetY}px)`;
// use matrix to solve the problem of elements not rendering due to safari optimization
style.transform = `matrix(${scale}, 0, 0, ${scale}, ${moveX}, ${moveY})`;
}

return style;
Expand Down Expand Up @@ -111,11 +116,31 @@ export default defineComponent({
return 0;
});

const setScale = (scale: number) => {
const setScale = (scale: number, center?: { x: number; y: number }) => {
scale = clamp(scale, +props.minZoom, +props.maxZoom + 1);

if (scale !== state.scale) {
const ratio = scale / state.scale;
state.scale = scale;

if (center) {
const imageRect = useRect(imageRef.value?.$el);
const origin = {
x: imageRect.width * 0.5,
y: imageRect.height * 0.5,
};
const moveX =
state.moveX - (center.x - imageRect.left - origin.x) * (ratio - 1);
const moveY =
state.moveY - (center.y - imageRect.top - origin.y) * (ratio - 1);

state.moveX = clamp(moveX, -maxMoveX.value, maxMoveX.value);
state.moveY = clamp(moveY, -maxMoveY.value, maxMoveY.value);
} else {
state.moveX = 0;
state.moveY = 0;
}

emit('scale', {
scale,
index: props.active,
Expand All @@ -125,23 +150,25 @@ export default defineComponent({

const resetScale = () => {
setScale(1);
state.moveX = 0;
state.moveY = 0;
};

const toggleScale = () => {
const scale = state.scale > 1 ? 1 : 2;

setScale(scale);
state.moveX = 0;
state.moveY = 0;
setScale(
scale,
scale === 2
? { x: touch.startX.value, y: touch.startY.value }
: undefined
);
};

let fingerNum: number;
let startMoveX: number;
let startMoveY: number;
let startScale: number;
let startDistance: number;
let lastCenter: { x: number; y: number };
let doubleTapTimer: ReturnType<typeof setTimeout> | null;
let touchStartTime: number;
let isImageMoved = false;
Expand Down Expand Up @@ -170,7 +197,7 @@ export default defineComponent({

if (state.zooming) {
startScale = state.scale;
startDistance = getDistance(event.touches);
startDistance = getDistance(touches);
}
};

Expand Down Expand Up @@ -207,8 +234,8 @@ export default defineComponent({
if (touches.length === 2) {
const distance = getDistance(touches);
const scale = (startScale * distance) / startDistance;

setScale(scale);
lastCenter = getCenter(touches);
setScale(scale, lastCenter);
}
}
};
Expand Down Expand Up @@ -279,7 +306,7 @@ export default defineComponent({

const maxZoom = +props.maxZoom;
if (state.scale > maxZoom) {
state.scale = maxZoom;
setScale(maxZoom, lastCenter);
}
}
}
Expand Down Expand Up @@ -331,6 +358,7 @@ export default defineComponent({
) : (
<Image
v-slots={imageSlots}
ref={imageRef}
src={props.src}
fit="contain"
class={bem('image', { vertical: vertical.value })}
Expand Down

0 comments on commit d05972d

Please sign in to comment.