diff --git a/src/hooks/useRive.tsx b/src/hooks/useRive.tsx
index 6abd179..0e35bdd 100644
--- a/src/hooks/useRive.tsx
+++ b/src/hooks/useRive.tsx
@@ -25,6 +25,8 @@ function RiveComponent({
setCanvasRef,
className = '',
style,
+ width,
+ height,
...rest
}: RiveComponentProps & ComponentProps<'canvas'>) {
const containerStyle = {
@@ -39,7 +41,12 @@ function RiveComponent({
className={className}
{...(!className && { style: containerStyle })}
>
-
+
);
}
@@ -82,6 +89,7 @@ export default function useRive(
const containerRef = useRef(null);
const [rive, setRive] = useState(null);
+ const riveRef = useRef(null);
const [dimensions, setDimensions] = useState({
height: 0,
width: 0,
@@ -92,6 +100,9 @@ export default function useRive(
const size = useSize(containerRef);
const isParamsLoaded = Boolean(riveParams);
+
+ const artboardParam = riveParams?.artboard;
+
const options = getOptions(opts);
/**
@@ -133,15 +144,25 @@ export default function useRive(
if (options.fitCanvasToArtboardHeight) {
containerRef.current.style.height = height + 'px';
}
+ const widthProp = canvasRef.current.dataset['rive-width-prop'];
+ const heightProp = canvasRef.current.dataset['rive-height-prop'];
if (options.useDevicePixelRatio) {
const dpr = window.devicePixelRatio || 1;
- canvasRef.current.width = dpr * width;
- canvasRef.current.height = dpr * height;
+ if (!widthProp) {
+ canvasRef.current.width = dpr * width;
+ }
+ if (!heightProp) {
+ canvasRef.current.height = dpr * height;
+ }
canvasRef.current.style.width = width + 'px';
canvasRef.current.style.height = height + 'px';
} else {
- canvasRef.current.width = width;
- canvasRef.current.height = height;
+ if (!widthProp) {
+ canvasRef.current.width = width;
+ }
+ if (!heightProp) {
+ canvasRef.current.height = height;
+ }
}
setDimensions({ width, height });
@@ -186,6 +207,9 @@ export default function useRive(
// on an unmounted component in some rare cases
if (canvasRef.current) {
setRive(r);
+ // Setting a ref in addition to state so that we can get a reference to the Rive
+ // instance on component unmount
+ riveRef.current = r;
}
});
} else if (canvas === null && canvasRef.current) {
@@ -214,8 +238,8 @@ export default function useRive(
useEffect(() => {
const observer = new IntersectionObserver(([entry]) => {
entry.isIntersecting
- ? rive && rive.startRendering()
- : rive && rive.stopRendering();
+ ? rive && riveRef.current && rive.startRendering()
+ : rive && riveRef.current && rive.stopRendering();
});
if (canvasRef.current) {
@@ -227,17 +251,46 @@ export default function useRive(
};
}, [rive]);
+ /**
+ * Reset Rive when the artboard, animations, or state machines change
+ */
+ useEffect(() => {
+ // Ensure at least the artboard is set before resetting Rive
+ if (artboardParam && rive) {
+ rive.stopRendering();
+ rive.stop();
+ rive.cleanup();
+
+ const { useOffscreenRenderer } = options;
+ const r = new Rive({
+ useOffscreenRenderer,
+ ...riveParams,
+ canvas: canvasRef.current as HTMLCanvasElement,
+ });
+ r.on(EventType.Load, () => {
+ if (canvasRef.current) {
+ setRive(r);
+ // Setting a ref in addition to state so that we can get a reference to the Rive
+ // instance on component unmount
+ riveRef.current = r;
+ }
+ });
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [artboardParam]);
+
/**
* On unmount, stop rive from rendering.
*/
useEffect(() => {
return () => {
- if (rive) {
- rive.stop();
- setRive(null);
+ if (riveRef.current) {
+ riveRef.current.stopRendering();
+ riveRef.current.stop();
+ riveRef.current.cleanup();
}
};
- }, [rive]);
+ }, []);
/**
* Listen for changes in the animations params
@@ -265,7 +318,7 @@ export default function useRive(
/>
);
},
- []
+ [setCanvasRef, setContainerRef],
);
return {