React
First, follow the installation instructions to add the NPM package @fancyapps/ui
.
Use the usePanzoom
hook sample code or create your own wrapper based on it:
js
import { useRef, useState, useCallback, useEffect } from "react";
import { Panzoom } from "@fancyapps/ui/dist/panzoom/";
import "@fancyapps/ui/dist/panzoom/panzoom.css";
import { canUseDOM } from "@fancyapps/ui/dist/utils/canUseDOM.js";
import { isEqual } from "@fancyapps/ui/dist/utils/isEqual.js";
export default function usePanzoom(options = {}) {
const storedOptions = useRef(options);
const [container, setContainer] = useState(null);
const [panzoomInstance, setPanzoomInstance] = useState(undefined);
const reInit = useCallback(() => {
if (panzoomInstance) {
panzoomInstance.destroy().init();
}
}, [panzoomInstance]);
useEffect(() => {
if (!isEqual(options, storedOptions.current)) {
storedOptions.current = options;
reInit();
}
}, [options, reInit]);
useEffect(() => {
if (canUseDOM() && container) {
const newPanzoomInstance = Panzoom(
container,
storedOptions.current
).init();
setPanzoomInstance(newPanzoomInstance);
return () => {
newPanzoomInstance.destroy();
};
} else {
setPanzoomInstance(undefined);
}
}, [container]);
return [setContainer, panzoomInstance];
}
ts
import { useRef, useState, useCallback, useEffect } from "react";
import {
type PanzoomOptions,
type PanzoomInstance,
Panzoom,
} from "@fancyapps/ui/dist/panzoom/";
import "@fancyapps/ui/dist/panzoom/panzoom.css";
import { canUseDOM } from "@fancyapps/ui/dist/utils/canUseDOM.js";
import { isEqual } from "@fancyapps/ui/dist/utils/isEqual.js";
export type PanzoomContainerRefType = <ContainerElement extends HTMLElement>(
el: ContainerElement | null
) => void;
export type usePanzoom = [PanzoomContainerRefType, PanzoomInstance | undefined];
export default function usePanzoom(
options: Partial<PanzoomOptions> = {}
): usePanzoom {
const storedOptions = useRef(options);
const [container, setContainer] = useState<HTMLElement | null>(null);
const [panzoomInstance, setPanzoomInstance] = useState<
PanzoomInstance | undefined
>(undefined);
const reInit = useCallback(() => {
if (panzoomInstance) {
panzoomInstance.destroy().init();
}
}, [panzoomInstance]);
useEffect(() => {
if (!isEqual(options, storedOptions.current)) {
storedOptions.current = options;
reInit();
}
}, [options, reInit]);
useEffect(() => {
if (canUseDOM() && container) {
const newPanzoomInstance = Panzoom(
container,
storedOptions.current
).init();
setPanzoomInstance(newPanzoomInstance);
return () => {
newPanzoomInstance.destroy();
};
} else {
setPanzoomInstance(undefined);
}
}, [container]);
return [setContainer, panzoomInstance];
}
Usage:
ts
function App() {
const [panzoomRef] = usePanzoom({
// Your custom options
});
return (
<div ref={panzoomRef} style={{ height: "400px" }}>
<img
className="f-panzoom__content"
src="https://lipsum.app/id/60/2000x1500"
width="2000"
height="1500"
alt="Sample image"
/>
</div>
);
}
Here is a sample of how to access the Panzoom API:
ts
const [panzoomRef, panzoomInstance] = usePanzoom({
// Your custom options
});
useEffect(() => {
if (panzoomInstance) {
// Access API
console.log(panzoomInstance.getContainer());
}
}, [panzoomInstance]);