Hey,
First and foremost thank you so much for this amazing project.
This is one the most well structured and modular systems I have had the pleasure to work with.
However, I would like to modify the zoom plugin.
I am trying to implement pinch to zoom (for trackpads and mouse (wheelEvent)).
This is similar to in browser experience.
For this I am using useGesture Library (https://use-gesture.netlify.app/)..
This is because hammer.js looks unmaintained and also doesn't support pinch to zoom for trackpads.
Currently my use-gesture-zoom hooks looks like the following.
import { useRef } from 'react';
import { useZoomCapability } from './use-zoom';
import { useCapability } from '@embedpdf/core/react';
import type { ViewportPlugin } from '@embedpdf/plugin-viewport';
import { useGesture } from '@use-gesture/react';
import type { ZoomState } from '../../lib';
export function useGestureZoom() {
const { provides: viewportProvides } = useCapability<ViewportPlugin>('viewport');
const { provides: zoomProvides } = useZoomCapability();
const elementRef = useRef<HTMLDivElement>(null);
const initialZoomRef = useRef(1);
const lastCenterRef = useRef({ x: 0, y: 0 });
const updateTransform = (scale: number) => {
if (!elementRef.current) return;
elementRef.current.style.transform = `scale(${scale})`;
};
const resetTransform = () => {
if (!elementRef.current) return;
elementRef.current.style.transform = 'none';
elementRef.current.style.transformOrigin = '0 0';
};
useGesture(
{
onPinchStart: ({ event, origin }) => {
if (!elementRef.current || !zoomProvides || !viewportProvides) return;
initialZoomRef.current = zoomProvides.getState().currentZoomLevel;
const viewerRect = elementRef.current.getBoundingClientRect();
lastCenterRef.current = {
x: origin[0] - viewerRect.left,
y: origin[1] - viewerRect.top,
};
elementRef.current.style.transformOrigin = `${lastCenterRef.current.x}px ${lastCenterRef.current.y}px`;
if (event.cancelable) {
event.preventDefault();
event.stopPropagation();
}
},
onPinch: ({ event, offset: [scale] }) => {
updateTransform(scale);
if (event.cancelable) {
event.preventDefault();
event.stopPropagation();
}
},
onPinchEnd: ({ offset: [scale], origin }) => {
if (!zoomProvides) return;
const delta = (scale - 1) * initialZoomRef.current;
const center = lastCenterRef.current;
zoomProvides.requestZoomBy(delta, { vx: center.x, vy: center.y });
resetTransform();
}
},
{
target: elementRef,
eventOptions: { passive: false },
pinch: {
scaleBounds: { min: 0.5, max: 3 },
rubberband: true,
from: () => [1, 0],
},
}
);
return { elementRef };
}
While zooming the transform is applied focusing at the correct coordinates but when requestZoomBy call is issued, the viewer jumps to someplace else. I don't understand why this might be the case.
Any help is appreciated.
Thanks again!
Hey,
First and foremost thank you so much for this amazing project.
This is one the most well structured and modular systems I have had the pleasure to work with.
However, I would like to modify the zoom plugin.
I am trying to implement pinch to zoom (for trackpads and mouse (wheelEvent)).
This is similar to in browser experience.
For this I am using
useGestureLibrary (https://use-gesture.netlify.app/)..This is because
hammer.jslooks unmaintained and also doesn't support pinch to zoom for trackpads.Currently my
use-gesture-zoomhooks looks like the following.While zooming the transform is applied focusing at the correct coordinates but when
requestZoomBycall is issued, the viewer jumps to someplace else. I don't understand why this might be the case.Any help is appreciated.
Thanks again!