bitttttten / mechanical-counter

A mechanical counter as seen on Robinhood. Recreated with framer-motion for react.
https://main--617315b23667c2003a0d878b.chromatic.com
23 stars 3 forks source link

counter animation glitches #1

Open bramdeba opened 2 years ago

bramdeba commented 2 years ago

The animation glitches. Any idea what may be causing this?

Kapture 2022-01-11 at 17 33 18

image

bitttttten commented 2 years ago

Hi @bramdeba ! Sorry I didn't see this earlier. Which font are you using? I can try and reproduce and let you know what's up.

This is a custom font, right? My first instinct is that the library could be calculating the spacing of the digits before the font is loaded. Or at least the library is failing to calculate the spacing properly.

You could try only displaying the component after the fonts have loaded, just to see if it fixes your issue. If it does then there is work to be done in the library :)

I would do something like this, just to test that it is the font loading causing the issue.

function useAreFontsReady() {
    const [state,set] = useState(false);

    useEffect(() => {
        document.fonts.ready.finally(() => {
            set(true);
        });
    }, []);

    return state
}

Then you can use it like

const areFontsReady = useAreFontsReady();

return areFontsReady ? <CounterAnimation text="testing" /> : null
bitttttten commented 2 years ago

Actually, that code able is in the repo already! Although if you can provide a bit more details about your environment, it might help me look into it.

I had actually noticed that I am not setting the font for the counter in the best way. It seems that the API is not very consistent across all browsers. So this line:

context.font = getComputedStyle(ref.current ?? document.body).font;

is very different in some browsers than others, and in some browsers, I was noticing that getComputedStyle().font does not return the font family, only the font size. So therefore the calculation will not be correct since the font is not set. I am using the canvas to measure the width of each letter, and the canvas font is not being set correctly, therefore the width of the letters is not being read correctly.

I am not sure if that is the problem for you, but it is a problem I have noticed.

bitttttten commented 2 years ago

I just released 1.0.14 although not sure it totally fixes it for you. Curious to know which browser and font combo you have.

johndebord commented 2 years ago

I'm having the same exact issue. Currently using Google Chrome Desktop and Safari iOS

johndebord commented 2 years ago

Narrowed down the problem; the bug appears when specifying margin=auto of a container element containing a MechanicalCounter

bitttttten commented 2 years ago

@johndebord Very cool that you were able to get to the bottom of it and thanks for sharing. Are you able to provide a reproduction? Perhaps in codesandbox or something? As I cannot reproduce here even with your description

commandZeta commented 1 year ago

I have a similar problem with the rendering of the elements

<MechanicalCounter text={ myFunction(price*quant) } />

return(
   new Intl.NumberFormat('es-AR', {
     style: style,
     currency: currency,
     minimumFractionDigits: 0
   }).format(calculatedAmount)
)

Reviewing the rendered HTML I see that it misapplies the location on the translate3D property, it displaces the numbers much further than they should, at the same time which leaves it with opacity 0.

For what it's worth, I had some issues between mechanical-counter and framer-motion (v 10.12.18) when installing the dependency. I think I fixed it by reinstalling framer-motion with "npm install framer-motion --legacy-peer-deps" but I don't remember exactly now

bitttttten commented 8 months ago

@commandZeta it could be some kind of framer-motion bug, maybe my code is also not very optimised 😅

the peer dep is "framer-motion": "^4.1.17",, although i imagine this would work with many other framer motion versions so i hope installing a different version fixes it 😬