Load animation once
Soarc opened this issue · 3 comments
I wondering, is there any way to load rive animation once and use in multiple places?
I had button component with loader animation on it. I used that button on multiple times on page and it results to unnessary http request for each button.
This is simplified version of component I use
import RiveComponent, { Alignment, Fit, Layout } from '@rive-app/react-canvas';
export const Button =() => {
return <button type="button" className="flex">
ClickMe
<RiveComponent src="/loading-wave.riv" layout={new Layout({ fit: Fit.Contain, alignment: Alignment.Center })} />
</button>
});
Probably related to #135
Since I'm using nextjs I was able to workaround animations loading via webpack url-loader.
You will need to install url-loader npm package and modify next.config.js.
const nextConfig = {
reactStrictMode: true,
webpack: (
config,
{ buildId, dev, isServer, defaultLoaders, nextRuntime, webpack }
) => {
config.module.rules.push({
test: /\.riv$/,
use: {
loader: "url-loader",
options: {
limit: 100000,
},
},
});
return config;
},
};
module.exports = nextConfig;
Now you will be able to use animations as modules
import LoadingWave from "assets/loading-wave.riv";
export const Button =() => {
return <button type="button" className="flex">
ClickMe
<RiveComponent src={LoadingWave} layout={new Layout({ fit: Fit.Contain, alignment: Alignment.Center })} />
</button>
});
I also needed to add rive.d.ts typescript definition definition to get rid off VSCode "cannot find module" errors.
declare module "*.riv" {
const value: string;
export default value;
}
We just released a new useRiveFile
hook that makes it easier to reuse a RiveFile instance.
Here's a simplified example of how you can use it:
import React, { useState } from 'react';
import { useRiveFile } from '@rive-app/react-canvas';
// Custom Wrapper component to display the Rive animation
const RiveAnimation = ({ riveFile }) => {
const { RiveComponent } = useRive({
riveFile,
autoplay: true
});
return <RiveComponent/>;
};
function App() {
const { riveFile, status } = useRiveFile({
src: 'https://cdn.rive.app/animations/myrivefile.riv',
});
const [instanceCount] = useState(5); // Number of RiveAnimation components to render
if (status === 'loading') {
return <div>Loading...</div>;
}
if (status === 'failed') {
return <div>Failed to load Rive file.</div>;
}
// Each RiveAnimation component uses the RiveFile we loaded earlier, so it is only fetched and initialized once
return (
<div className="App">
<header className="App-header">Rive Instances</header>
<div className="rive-list">
{Array.from({ length: instanceCount }, (_, index) => (
<RiveAnimation key={`rive-instance-${index}`} riveFile={riveFile} />
))}
</div>
</div>
);
}
export default App;