Wobbling Vertical Progress Bar
I learned how to build a neat, dynamically sized vertical progress bar with cross-bars in This Question.
Now, I want to make it fun!
The bar's wobble function should:
- take 4 parameters:
element
, height
, speed
, & random
- wobble the
element
height percentage with a customizable, randomized factor
- keep track of the elements's true height, which can change at any time!
- use an event (in the Fiddle, I supply an input and button) to set the true height to a new value, and animate to that height.
I'm looking for the simplest answer. Please explain how you did it, so that we JS newbies can learn tricks! Posting a Bounty of +50 to the best answer.
Bonus:
- change the bars's background color value based on the bar's true height. Red is 0%, Yellow is 50%, and Green is 100%;
If your function does this too, I'll add a +100 Bounty to your answer instead.
Template Fiddle
My Progress
I'm asking this question because I don't know how to do this yet.
But, I'm going to try it from what I've learned so far, and keep my
progress posted here.
So here's my JSFiddle take on it.
Comments should be self explanatory. I had to add JQuery UI for the animation effects with easing. I'm not sure what you meant by random
, but speed should be all you need to change.
Sorry, no animation in the screenshots.
Really enjoyed playing with this, so thank you :) I took a different approach but with much less code. I think I went a bit overboard with the colors, if needed I can change it back to red yellow green.
http://jsfiddle.net/3wN77/23/
$('#change-height').on('click', function() {
var element = $('.attendance-level');
var height = parseInt( $('#true-height').val() ); // %
var speed = 1000; //ms
var random = 50; //px
bar_wobble( element, height, speed, random );
});
function bar_wobble(element, height, speed, random) {
//set the color
$(element).css('-webkit-filter','hue-rotate('+ 140*(250/height) +'deg)'); //red = 0 deg, green = 140deg
//wibbly wobbly timey wimey stuff
height = height/100*250;
var number_of_wobbles = 3;
for(var i=1; i<=number_of_wobbles; i++)
{ $(element).animate({ height: (height + random/i )+'px'}, speed/(number_of_wobbles*2 + 1));
$(element).animate({ height: (height - random/i )+'px'}, speed/(number_of_wobbles*2 + 1));
console.log( {i: i, random_i: random/i, random:random, height:height } );
}
$(element).animate({ height: height+'px'}, speed/(number_of_wobbles*2 + 1));
}
Don't think StackOverflow is meant for these kind of 'questions', but oh well, felt like it, so made a far more extensive answer than a sane person would.
Let me start with a couple of technologies I incorporated and their justification
- SVG, it feels terribly wrong when DOM is used to shape an image. Either actual images should be used for the background/foreground, or one should use something like SVG instead of DOM. The disadvantage of SVG is that it can only provide uniform scaling.
X-Tags, X-tags is a Web Components Custom Element polyfill developed by Mozilla. It allows us to write something like
<x-bar id="test"></x-bar>
And then do
var xbar1 = document.getElementById("test");
xbar1.value = 10;
xbar1.speed = 2;
xbar1.wobble = 10;
xbar1.effect= "dampen";
Cool right? This however means you will first need to read the documentation here. Before you will be able to understand the code.
- Javascript for the animations: Although you could make some elemantary wobble using CSS3 animations, the requirement for the control over it and the colour change requirement makes one choose for Javascript.
- Two wobble effects are incorporated, a simple
y=sin(t)
and a more complexed dampened wave. One could easily add other waves as well, but these seemed to be the most reasonably interesting ones.
- Regarding the code to calculate the colour. I am simply splitting the bar in two halves, for the top half I define a colour range from green to orange and for the second half from orange to red. Next in the code I 'find the point' between those two colours depending on how filled the bar is. (E.g. if we're at 80% filled of the total bar, it means that we're at 60% of the top half, so we take that point between orange and green)
As the code itself is over 200 lines long I will refrain from posting it here and you can find it on this jsfiddle.