Reputation: 23
I have been trying to smooth out the transitions on this snippet of code but I don't understand why that transition is not working. I'm trying to not use anything outside of vanilla HTML, CSS, and JavaScript. I know I can achieve a similar result with pure CSS using key animations but I'm very curious if it can be done using mostly js. How can this be done?
<head>
<style>
*{
transition: all 5s !important;
}
div{
width: 100vw;
height: 100vh;
}
</style>
</head>
<div id='gradient'>
<h1>hello</h1>
</div>
<script>
document.querySelector("#gradient").style.backgroundImage= 'linear-gradient(60deg, #3d3393 0%, #2b76b9 37%, #2cacd1 65%, #35eb93 100%)';
function dynamicGradient() {
let color1 = `rgb(${Math.random()*100+55},${51},${Math.random()*20+100})`
let color2 = `rgb(${Math.random()*10+13},${78},${Math.random()*10+135})`
let color3 = `rgb(${Math.random()*10+14},${Math.random()*5+184},${Math.random()*10+160})`
let color4 = `rgb(${Math.random()*5+28},${Math.random()*10+185},${Math.random()*10+67})`
let linearGradient = `linear-gradient(60deg, ${color1} 10%, ${color2} 37%, ${color3} 65%, ${color4} 100%)`
document.querySelector("#gradient").style.backgroundImage = linearGradient;
document.querySelector("#gradient").style.backgroundImage.filter = 'blur(200px)';
console.log('called')
}
setInterval(() => {
dynamicGradient()
}, 800);</script>
Upvotes: 1
Views: 313
Reputation: 65796
CSS transitions don't work here because background-image
is treated like an image and transitions require numeric values to interpolate.
But there are non-transition solutions, like this one from: https://opticalcortex.com/animating-css-gradients/
// target to give background to
var $div = document.getElementById("gradient");
// rgb vals of the gradients
var gradients = [
{ start: [128,179,171], stop: [30,41,58] },
{ start: [255,207,160], stop: [234,92,68] },
{ start: [212,121,121], stop: [130,105,151] }
];
// how long for each transition
var transition_time = 4;
// internal type vars
var currentIndex = 0; // where we are in the gradients array
var nextIndex = 1; // what index of the gradients array is next
var steps_count = 0; // steps counter
var steps_total = Math.round(transition_time*60); // total amount of steps
var rgb_steps = {
start: [0,0,0],
stop: [0,0,0]
}; // how much to alter each rgb value
var rgb_values = {
start: [0,0,0],
stop: [0,0,0]
}; // the current rgb values, gets altered by rgb steps on each interval
var prefixes = ["-webkit-","-moz-","-o-","-ms-",""]; // for looping through adding styles
var div_style = $div.style; // short cut to actually adding styles
var color1, color2;
// sets next current and next index of gradients array
function set_next(num) {
return (num + 1 < gradients.length) ? num + 1 : 0;
}
// work out how big each rgb step is
function calc_step_size(a,b) {
return (a - b) / steps_total;
}
// populate the rgb_values and rgb_steps objects
function calc_steps() {
for (var key in rgb_values) {
if (rgb_values.hasOwnProperty(key)) {
for(var i = 0; i < 3; i++) {
rgb_values[key][i] = gradients[currentIndex][key][i];
rgb_steps[key][i] = calc_step_size(gradients[nextIndex][key][i],rgb_values[key][i]);
}
}
}
}
// update current rgb vals, update DOM element with new CSS background
function updateGradient(){
// update the current rgb vals
for (var key in rgb_values) {
if (rgb_values.hasOwnProperty(key)) {
for(var i = 0; i < 3; i++) {
rgb_values[key][i] += rgb_steps[key][i];
}
}
}
// generate CSS rgb values
var t_color1 = "rgb("+(rgb_values.start[0] | 0)+","+(rgb_values.start[1] | 0)+","+(rgb_values.start[2] | 0)+")";
var t_color2 = "rgb("+(rgb_values.stop[0] | 0)+","+(rgb_values.stop[1] | 0)+","+(rgb_values.stop[2] | 0)+")";
// has anything changed on this interation
if (t_color1 != color1 || t_color2 != color2) {
// update cols strings
color1 = t_color1;
color2 = t_color2;
// update DOM element style attribute
div_style.backgroundImage = "-webkit-gradient(linear, left bottom, right top, from("+color1+"), to("+color2+"))";
for (var i = 0; i < 4; i++) {
div_style.backgroundImage = prefixes[i]+"linear-gradient(45deg, "+color1+", "+color2+")";
}
}
// we did another step
steps_count++;
// did we do too many steps?
if (steps_count > steps_total) {
// reset steps count
steps_count = 0;
// set new indexs
currentIndex = set_next(currentIndex);
nextIndex = set_next(nextIndex);
// calc steps
calc_steps();
}
if (div_style.backgroundImage.indexOf("gradient") != -1) {
window.requestAnimationFrame(updateGradient)
}
}
// initial step calc
calc_steps();
// go go go!
window.requestAnimationFrame(updateGradient);
#gradient {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: #836997;
}
<div id="gradient"></div>
Upvotes: 1