dotlottie-web
dotlottie-web copied to clipboard
Failed to construct 'ImageData': The source width is zero or not a number.
Overview
Error that's occuring wrapper with display:none and framer motion of a <DotLottieReact /> component
Failed to construct 'ImageData': The source width is zero or not a number.
Sometimes
Consuming repo
What repo were you working in when this issue occurred?
@lottiefiles/dotlottie-react
Hi @sulram, when using display: none, the width and height of the DotLottieReact canvas are set to zero, causing the error.
You can use the hidden prop directly on the DotLottieReact component. This keeps the component in the DOM without rendering it visibly:
<DotLottieReact hidden ... />
also you can use other CSS properties like visibility or opacity:
<DotLottieReact style={{ visibility: 'hidden' }} ... />
<DotLottieReact style={{ opacity: 0 }} ... />
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs.
I experience this issue with Web using vanilla JS, but the parent element also need to be set to display none because I'm working on a mobile nav which at the desktop screen should be hidden. Is there any other workaround to it?
Still getting this issue with the following code:
import { Wordmark } from "@dub/ui";
import { DotLottieReact } from "@lottiefiles/dotlottie-react";
export default function AnimatedWordmark() {
return (
<div className="group relative h-6">
<Wordmark className="absolute h-6 group-hover:opacity-0" />
<DotLottieReact
src="https://lottie.host/f53c93bf-8ae7-4f55-a73e-fbdf36e5c062/4KoxyK0Ruc.json"
playOnHover
loop
className="absolute h-6 opacity-0 group-hover:opacity-100"
/>
</div>
);
}
Thanks @steven-tey for the code, I'll investigate it further
Solution Found ✅
I encountered the same issue with NextJS. I attempted to use Telegram animated emojis (convert TGS to JSON). While the animation works fine for the top emoji, it fails for others and displays an error message ('ImageData': The source width is zero or not a number.) 🧐.
I added the same code to the other emojis animation sections, and they all started working without any errors. 😅 I have no idea why the animation works after adding <div className=“flex flex-col items-center gap-1”></div> as the parent container.
Code with Error:
<div
key={`div-${id}`}
ref={ref}
style={{ width: `${size}px`, height: `${size}px` }}
>
{inView ? (
<DotLottieReact
id={id}
data={jsonData}
autoplay={autoplay}
loop={loop}
className={className}
renderConfig={{
autoResize: true,
}}
/>
) : (
<></>
)}
</div>;
Screenshot
Working Code:
<div className="flex flex-col items-center gap-1">
<div
key={`div-${id}`}
ref={ref}
style={{ width: `${size}px`, height: `${size}px` }}
>
{inView ? (
<DotLottieReact
id={id}
data={jsonData}
autoplay={autoplay}
loop={loop}
className={className}
renderConfig={{
autoResize: true,
}}
/>
) : (
<></>
)}
</div>
</div>;
I encounter the exact same problem. The issue is very simple to reproduce: it occurs everytime you init a DotLottie when the canvas given in parameter is not shown (display none for instance)
I set up a very simple codepen here: https://codepen.io/nyroDev/full/VYZQdGZ
When using "Init on shown element", it's working correctly, nothing to say here.
When using "Init on hidden element", the canvas given in the config is under a div which is hidden by CSS.
When clicking on it, we have the error:
"Failed to load animation data from URL: https://lottie.host/0cbdb3ef-2fa5-4d1d-9e4e-f66c879e010d/D0bRr9d93F.lottie. IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number."
After trying to dig a little bit on it, I found out that width and height of canvas is read on init here.
So I added a third test which add width and height as attribute of the canvas.
This it not working too.
I guess there might be something elsewhere trying to get the dimensions of the canvas which return 0 when i'ts not displayed.
For now, this bug make it impossible to instantiate a dotLottie located on a DOM element which is not displayed.
After digging more, I found the exact reason why it's occurring.
On load, when doing it in browser, a call to the resize function is done.
On this resize function, the native getBoundingClientRect function is used.
This function will always return everything to 0 when element is hidden (display none)
And the width/height of the canvas is then rewritten into the DOM.
So it reinitialize the value to 0/0 and that's where the bug starts...
In my opinion, the resize should not rewrite value to the DOM canvas.
Or maybe we should have a new RenderConfig setting to control that?
Moreover, the first resize should NOT depends on getBoundingClientRect.
Regarding the latter resizes, I guess it should be OK to rely on this function.
Right now, I came up with a very dirty way to fix this bug.
Just before initializing the DotLottie instance, I'm overwriting the getBoundingClientRect to return the value expected by the library.
I updated the codepen to show the working result: https://codepen.io/nyroDev/full/VYZQdGZ
Thanks, @nyroDev, for the detailed investigation and for documenting the issue so clearly.
A possible improvement could be to offload the decision of resizing to the render loop. By comparing the canvas drawing area's width and height with the internal framebuffer dimensions: • If they match, we proceed with rendering • If not, we leave the canvas dimensions as-is and adjust the frame buffer to align with the drawing area
And if the canvas width and height are zeros as in this case, then we can skip rendering.
This approach could potentially address the issue without rewriting values to the DOM canvas unnecessarily. but, I’ll need to test this thoroughly to ensure it handles all edge cases and remains backward-compatible with the current behavior.
As for adding a RenderConfig setting to control this, I think it’s a viable idea worth exploring to give users more flexibility over how resizing is handled
In my opinion, the resize should not rewrite value to the DOM canvas. Or maybe we should have a new RenderConfig setting to control that? Moreover, the first resize should NOT depends on getBoundingClientRect. Regarding the latter resizes, I guess it should be OK to rely on this function.
Thanks again for raising this and for providing a working example, it’s very helpful for debugging
The fix will be available in dotlottie-react v0.12.3
The fix will be available in dotlottie-react v0.12.3
And dotlottie-wc v0.4.4 If I undestood correctly.
Thanks @theashraf
The fix will be available in dotlottie-react v0.12.3
And dotlottie-wc v0.4.4 If I undestood correctly.
Thanks @theashraf
@nyroDev yes
@nyroDev I’ve used your example as a way to check if the fix is working—super helpful!
I’ve made a tiny update to the 3rd canvas example, where we need to call the resize method after the canvas becomes visible. Alternatively, you can pass a property to the renderConfig called autoResize, which should handle this case automatically as well
https://codepen.io/lottiefiles/pen/EaYGbQK
I can confirm that the last release fix this bug. Thanks for the quick release!
@theashraf the resize seems to be NOT required.
On your codepen, it's actually commented (and was in the 2nd exemple anyway)
@theashraf @nyroDev This issue has been fixed in the latest release but the quality of the dotLottie seems to be poor quality which renders instead of the earlier error. However, when i reload the page, the quality is what it is supposed to be
Also this another error occurs which seems apparently related but has no effect on UI : IndexSizeError: Failed to construct 'ImageData': The input data length is not equal to (4 * width * height).
I think dotlottie-vue still have this issue, add autoResize: true will still happen this issue. but even if this issue occur, not affect the animation display