HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Animating the percent of a "percentage bar" during the transition

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thebarduringpercentanimatingtransitionpercentage

Problem

I have created a very basic animated percentage bar with HTML, CSS, and JS the only problem is that I am trying to devise a way to also animate the increase and/or decrease of the percentage output to go along with an animated percentage bar. In the example below and in this JsFiddle I have successfully created that with the only problem being that it doesn't seem to be the most efficient or effective way of doing it.

In the code snippet directly below I'm creating this animated effect by...

  • Setting x equal to setInterval



  • Capturing the width of percent bar on the left and removing the px from the end of the string.



  • Capturing the width of percent bar on the right and removing the px from the end of the string.



  • Displays the percent value for the left (blue) bar inside the tooltip that can be seen when hovered over.



  • Displays the percent value for the right (red) bar inside the tooltip that can be seen when hovered over.



  • Displays the percent value of the left (blue) bar below the percent bar.



  • Displays the percent value of the right (red) bar below the percent bar.



  • All of this code below will run every 64 Milliseconds.



  • This code will only run for 2000 Milliseconds which is the same amount of time that I have set the transition for the percent bars.



Note: The whole point of the code below is to give the illusion that the percent values are increasing as either of the percent bars are increasing. In short, the goal is to make it seem more animated rather than the number all of a sudden seeing the number jump from one number to the next.

There just has to be a better way of achieving the same effect (or better) rather than pulling data from the DOM every 64 Milliseconds. There are tons of real-time graph's out on the web that achieve the same effect but I can't figure out how so I came up with my own and don't really think that they do it this way either. Any ideas??? I would only like to use pure Javascript with no libraries su

Solution

From my experience, the main problem I see is that you are having a hard time differentiating what is domain logic from view.
As a consequence, you are giving responsibilities to your javascript code that make it more complicated.

In summary:


Prefer CSS to handle the view, and JS to handle the changes you want
to make in your model (HTML).

The domain logic of your problem is reduced to:

$$Percentage\,of\,blue\,bar = 100 * \frac{good}{total}\quad(By\,rule\,of\,three)$$

And now with this percentage you can achieve anything you want as
$$Percent\,of\,red\,bar = 100 - Percentage\,of\,blue\,bar$$

In the following example, I control this by using the HTML5 progress element

Codepen with Percentage Bar made using HTML5 progress element

Look that all logic comes down to:

  • When you press Good => increment good and total, then update the model.



  • When Bad is pressed => only increment total. Making a bad counter is unnecessary and complicates things.



  • To update the model => make the width of your bar to be the value returned by the mentioned formula. In my code; completed() function refers to the formula.



The most complex case in this scenario, is to calculate the difference between last percentage, however, it is not required in any way to solve your problem.

Now, time for the logic of the view. CSS allows to make animations of this type using for example; transition property. In the following code I only tweked the progress bar like the one you presented:

Codepen with the expected Percentage bar

Note that the only property responsible for all the logic is

transition: width .3s ease-out;


Being:

  • width: the value that represents the percentage. The one you use to change it from js



  • .3s (or 0.3s): is the time I want the animation to last



  • ease-out: is one of the standard animations provided.



In case you want to handle the animation using only js, the common scenario to do it, would be in case of drawing directly on screen, like using the canvas element (Specially used when developing games). However, developing this logic is quite more complex and unnecessary for most cases, since you have to take care of available hardware resources where js code will be executed.

This is the approximation which you tried to solve the problem, and if you still have curiosity: Yes there is a better way to solve it (And probably, always exist better ways to solve common things). However you have to take into account that generally when drawing directly on the screen, one decides the size of the elements, reason why it simplifies the problem enough since now you would know the maximum width of your progress bar.

Knowing this, the logic of the view would now be something more like:

  • Starting a loop that lasts the time you expect will be your animation length (.3s is the time I used). This can be achieved in several ways, with setInterval, setTimeout, using classic loops referencing the current time, or preferably using window.requestAnimationFrame that is particularly developed for this task.



  • And inside the loop, you only have to change the width of the rectangle that would represent the element of the bar, making the product of the maximum width of the progress bar with the percentage already calculated (good/total)



Edit: I missunderstood the question, so i continued here:

I can't think a pure CSS solution for this, but if exist, it would be better than this.

This is how i could do the same, but using the last approach.

Preview

However @blackmiaool pointed most corrections, but one thing i tough was important and not pointed:

element.addEventListener('transitionend', function() {
  //Logic to stop your animation. Like showing your final expected value
});


If you use this, you can decouple your animation time, so, you can change your CSS transition time to whatever without changing your code.

PD: I'm not english speaker, so, i will be glad if someone can correct my mistakes :)

Code Snippets

transition: width .3s ease-out;
element.addEventListener('transitionend', function() {
  //Logic to stop your animation. Like showing your final expected value
});

Context

StackExchange Code Review Q#159524, answer score: 3

Revisions (0)

No revisions yet.