I'm trying to make a "progress bar" with animation that changes the background colour of the bar.
The bar should start with red at 0% and as it progresses across the element it changes to green at 100%. I've got this working for 100% (and no, the colour is not great, but that's a future problem)...
setTimeout(function(){
var bar = document.getElementById("bar");
bar.style.width = "100%";
bar.classList.add("show");
},10);
#progress {
border:1px solid #888;
background-color:#eee;
height:
width:100%;
}
#bar {
height:30px;
background-color:red;
width:0;
transition: all ease 1s;
}
#bar.show {
background-color:lightgreen;
}
<div id="progress"><div id="bar"></div></div>
The problem is that (for example) at 50% I cannot get the bar to "stop" at the 50% transition state between the red and the green.
Is there a way to either calculate the colour as it would be at 50% or get CSS to stop the transition at a particular point?
You can see what happens if I have a 50% value... where it still goes all the way to green but stops at the 50% width, but what I want it to do is stop at the 50% transition colour (i.e. going from red to mid-way between red and green)...
setTimeout(function(){
var bar = document.getElementById("bar");
bar.style.width = "50%";
bar.classList.add("show");
},10);
#progress {
border:1px solid #888;
background-color:#eee;
height:
width:100%;
}
#bar {
height:30px;
background-color:red;
width:0;
transition: all ease 1s;
}
#bar.show {
background-color:lightgreen;
}
<div id="progress"><div id="bar"></div></div>
Additional Info (as requested by 0stone0) the percentage value will not be known at the time the page is loaded, but will be provided via an AJAX call.
'Stopping' a gradient transition could be quite difficult.
Please consider an alternative approach, one where you manually calculate the desired final color. Use this color value as the target for the transition. This way there's no need to 'stop' the transition, since the final colour is already proportional to the percentage.
I've used this function to calculate the gradient between green and red, based on the percentage.
To ensure the bar is always clickable, we've moved the onClick to the .progress div so we can render the .bar at 0 width.
(Updated answer, based on comments)
function load(progress, perc) {
var bar = progress.getElementsByClassName("bar")[0];
bar.style.width = perc.toString() + "%";
bar.style.backgroundColor = getGradient(perc / 100);
}
function getGradient(ratio) {
var color1 = '90ee90'; // lightgreen
var color2 = 'FF0000'; // red
var hex = function(x) {
x = x.toString(16);
return (x.length == 1) ? '0' + x : x;
};
var r = Math.ceil(parseInt(color1.substring(0,2), 16) * ratio + parseInt(color2.substring(0,2), 16) * (1-ratio));
var g = Math.ceil(parseInt(color1.substring(2,4), 16) * ratio + parseInt(color2.substring(2,4), 16) * (1-ratio));
var b = Math.ceil(parseInt(color1.substring(4,6), 16) * ratio + parseInt(color2.substring(4,6), 16) * (1-ratio));
return '#' + hex(r) + hex(g) + hex(b);
}
.progress {
border:1px solid #888;
background-color:#eee;
height:30px;
width:100%;
}
.bar {
height:30px;
background-color:red;
width:0;
transition: all ease 1s;
}
Click to run...<br/>
<div class="progress" onclick='load(this, 25)'><div class="bar">25%</div></div>
<div class="progress" onclick='load(this, 50)'><div class="bar">50%</div></div>
<div class="progress" onclick='load(this, 75)'><div class="bar">75%</div></div>
<div class="progress" onclick='load(this, 100)'><div class="bar">100%</div></div>
(Original answer)
function load(bar, until) {
var p = 0;
setInterval(function() {
// Clear on complete
if (p > until) {
clearInterval(this);
return;
}
// Update Bar
bar.innerHTML = p;
bar.style.background = getGradient((p/1)/100);
bar.style.width = p + "%";
// Bump percentage
p++;
}, 100);
}
function getGradient(ratio) {
var color1 = '90ee90'; // lightgreen
var color2 = 'FF0000'; // red
var hex = function(x) {
x = x.toString(16);
return (x.length == 1) ? '0' + x : x;
};
var r = Math.ceil(parseInt(color1.substring(0,2), 16) * ratio + parseInt(color2.substring(0,2), 16) * (1-ratio));
var g = Math.ceil(parseInt(color1.substring(2,4), 16) * ratio + parseInt(color2.substring(2,4), 16) * (1-ratio));
var b = Math.ceil(parseInt(color1.substring(4,6), 16) * ratio + parseInt(color2.substring(4,6), 16) * (1-ratio));
return '#' + hex(r) + hex(g) + hex(b);
}
.progress {
border:1px solid #888;
background-color:#eee;
height: 50px;
width:100%;
}
.bar {
height:100%;
width:100%;
}
<div class="progress"><div onClick='load(this, 100)' class="bar"></div></div>
<div class="progress"><div onClick='load(this, 50)' class="bar"></div></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With