Animate Your Digits Like Robinhood

I want to use this animation (or an animation like this) for the user’s score to highlight the peaks and dips in their learning curve.

NOTE: For my app I have restricted the possibility for getting a negative score.

Negative numbers don’t always work as planned with this code.

‘NOTHER NOTE: In my app, I also make use of a NumInt component.

I pass the individual digits (in addition to a few other props) to this component and render them inline so they appear like a continuous number.

Abstracting this logic into digit components made it easier to consolidate props and manage the animation assignment.

Now onto the code!I keep the total in my parent component’s state, and when the total changes (when someone pops a balloon), I declare a variable that represents the total plus or minus whatever number is assigned to the balloon they just popped.

This occurs in calcPoints.

I convert the new number and the this.

state.

total to strings so I can split them into arrays.

By splitting them into arrays I can compare the integers are the same indexes of the corresponding arrays.

I pass the new total and the this.

state.

total (now arrays of of integers as strings) to checkNums.

This is where I compare the digits against one another, as well as the original new total and this.

state.

total.

This is my first solution, but it is not the final.

Stay tuned!There are a few conditionals here, each is responsible for evaluating the different outcomes that could happen in the comparison and pushing objects into an array.

The objects will contain the color and a true false, or null value.

We’ll go over the purpose of the array in a little bit but for now, here’s how we decide which value to push into the array.

The new total is greater than the previous total (color is green)Then evaluate the numbers.

If first number is greater (bool is true), or if second number is greater (bool is false), if no change (bool is null).

Or the new total is less than the previous total (color is red), then evaluate the numbers.

Finally, the two numbers could be the same (no color change), then compare the numbers.

‘Member that array I mentioned like 8 lines earlier?Once we have our array of objects, we store it in our state as truesArr.

So if were to run…console.

log(checkNums([‘2’, ‘0’, ‘0’, ‘0’], [‘1’, ‘0’, ‘0’, ‘5’]))…the logged array would look like this:Once we set this in our state, we can map through it in our render and return a NumInt component for each iteration.

For each NumInt component, we will pass three values:The child component keyThe individual digit from the total at that same indexThe hash containing the true/false/null value and the colorNow, onto our TurnNumInt component:Here we use PureComponent because TurnNumInt is a simple component that has no local stateThen we assign the className to the component (which is just a p tag) based on the props we received.

If the bool is true and the color is green, assign greenIntUp as the className.

This will trigger the animation for a digit that is both greater than the previous one as well as the overall number being greater than the previous.

Example: new total is 125 and previous total was 110.

If the bool is true and the color is red, assign redIntUp as the className.

This will trigger the animation for a digit that is greater than the previous one but the overall number being less than the previous.

Example: new total is 115 and previous total was 120.

The animation is the same as the previous one, but the color of the element is red.

If the bool is false and the color is green, assign greenIntDown as the className.

This will trigger the animation for a digit that is less than the previous one but the overall number being greater than the previous.

Example: new total is 120 and previous total was 115.

If the bool is false and the color is red, assign red as the className.

This will trigger the animation for a digit that is less than the previous one and the overall number being less than the previous.

Example: new total is 110 and previous total was 115.

I still need to work on the animation itself to achieve something that better mirrors the Robinhood animation but for now here is our result:So the logic I first implemented seems to work!.But is it really the best solution?Definitely not.

I figure there had to be a more efficient way to accomplish what I was trying to do.

But I struggled to find solutions online that were more efficient.

Some had less lines of code which is good but were not functionally more efficient.

So I turned to Stack Overflow and asked what I needed as it pertained to my use case.

The better you are at asking questions on Stack the quicker you’ll get a response and you’ll likely get a good response!.For more on how to ask good questions on stack, click here.

I got two good responses within minutes, and the solution I decided to go with was this one, from Nina Scholz.

I was definitely confused when I first saw this, so if you are too don’t feel bad.

Let’s break it down:First, we don’t bother with converting the numbers to strings and then splitting them into arrays.

We simply pass the numbers themselves.

This brings us to digit, which acts as comparative function.

This will be run at the end of the function, receiving an argument of whatever number is at that point in the iteration and when we finally start to create the final array.

It will be run for both the new and previous total for the amount of iterations specified by length.

Next, we assign the color.

This is rather simple.

If the new total is greater than the previous total, the color is green.

Otherwise it is red.

After the color, we can create and return the array that will be the value of this.

state.

truesArr.

Math.

ceil(Math.

log10(Math.

max(a, b))) will set the number of iterations.

Math.

max(a, b) finds the length of the largest of the two numbers.

Math.

log10(…) finds the base 10 logarithm of a number.

Math.

ceil(…) finds the smallest integer greater than or equal to a given number.

This line is complex and I won’t cover all of it in this post, but the important thing to know is that if you were to write…Math.

ceil(Math.

log10(Math.

max(1001, 1000)))…you would get 4.

This means you would iterate 4 times, the underscore in the next line represents the length, and i is the current value of the iteration.

((l, r) => l === r ? {color: color, bool: null } : {color: color, bool: l > r})This line is where we evaluate the digits.

If they are equal, pass the color and null.

It will not rotate in any particular way but it will change to the appropriate color.

And then if they are not equal, pass the color and the result of whether or not the first number is larger than the second.

(…[a, b].

map(digit(i)))Then we run the comparative function from earlier, digit, at every iteration in the final map function which will create the final array.

And finally, we run .

reverse() on the final array so that the objects align with the correct digit.

If we didn’t include this simple JS function at the end of our compare function, it could change the application of the function completely.

For instance, console.

log(compare(1001, 1000)) should log……which would animate the number in the ones position.

This would be correct because that’s the number that’s changing.

Had we left out the .

reverse() function at the end, we would log…As you can see, the color is correct and the bool value is correct but the placement is not.

This would result in the animation of the thousands place, which as you know is not correct because 1001 and 1000 have the same digit in the thousands place.

And there you have it, the logic behind conditionally applying individual animations to digits in a number.

I’ll likely write a follow up post about how to achieve a better Robinhood-like animation.

The animation I’ve given is very basic and while it resembles the Robinhood animation it is far from it.

If you enjoyed the post or need clarification on anything mentioned, let me know in the comments.

Please share and leave claps!ReferencesRobinhood – Invest for FreeInvest in stocks, options, ETFs, and cryptos, all commission-free.

$0 minimum deposit.

Secure platform trusted by…www.

robinhood.

comIs there a way to compare the corresponding integers in two numbers without converting them to…I am trying to conditionally apply animations to integers in a number based on whether or not the value of the number…stackoverflow.

comReact Top-Level API – ReactReact is the entry point to the React library.

If you load React from a tag, these top-level APIs are available on the…reactjs.

orgHow do I ask a good question?.- Help CenterStack Overflow | The World's Largest Online Community for Developersstackoverflow.

comUser Nina ScholzStack Overflow | The World's Largest Online Community for Developersstackoverflow.

comMath.

log10()The Math.

log10() function returns the base 10 logarithm of a number, that isdeveloper.

mozilla.

org.

. More details

Leave a Reply