Continuous Color Transition
Solution 1:
Check this JSFiddle for a transition with a fancy graph.
/* ==================== Required Functions ==================== */// This is required to get the initial background-color of an element.// The element might have it's bg-color already set before the transition.// Transition should continue/start from this color.// This will be used only once.functiongetElementBG(elm) {
var bg = getComputedStyle(elm).backgroundColor;
bg = bg.match(/\((.*)\)/)[1];
bg = bg.split(",");
for (var i = 0; i < bg.length; i++) {
bg[i] = parseInt(bg[i], 10);
}
if (bg.length > 3) { bg.pop(); }
return bg;
}
// A function to generate random numbers.// Will be needed to generate random RGB value between 0-255.functionrandom() {
if (arguments.length > 2) {
return0;
}
switch (arguments.length) {
case0:
returnMath.random();
case1:
returnMath.round(Math.random() * arguments[0]);
case2:
var min = arguments[0];
var max = arguments[1];
returnMath.round(Math.random() * (max - min) + min);
}
}
// Generates a random RGB value.functiongenerateRGB(min, max) {
var min = min || 0;
var max = min || 255;
var color = [];
for (var i = 0; i < 3; i++) {
var num = random(min, max);
color.push(num);
}
return color;
}
// Calculates the distance between the RGB values.// We need to know the distance between two colors// so that we can calculate the increment values for R, G, and B.functioncalculateDistance(colorArray1, colorArray2) {
var distance = [];
for (var i = 0; i < colorArray1.length; i++) {
distance.push(Math.abs(colorArray1[i] - colorArray2[i]));
}
return distance;
}
// Calculates the increment values for R, G, and B using distance, fps, and duration.// This calculation can be made in many different ways.functioncalculateIncrement(distanceArray, fps, duration) {
var fps = fps || 30;
var duration = duration || 1;
var increment = [];
for (var i = 0; i < distanceArray.length; i++) {
var incr = Math.abs(Math.floor(distanceArray[i] / (fps * duration)));
if (incr == 0) {
incr = 1;
}
increment.push(incr);
}
return increment;
}
// Converts RGB array [32,64,128] to HEX string #204080// It's easier to apply HEX color than RGB color.functionrgb2hex(colorArray) {
var color = [];
for (var i = 0; i < colorArray.length; i++) {
var hex = colorArray[i].toString(16);
if (hex.length < 2) { hex = "0" + hex; }
color.push(hex);
}
return"#" + color.join("");
}
/* ==================== Setup ==================== */// Duration is not what it says. It's a multiplier in the calculateIncrement() function.// duration = 1-4, fast-to-slowvar fps = 30;
var duration = 3;
var transElement = document.body;
var currentColor = getElementBG(transElement);
var transHandler = null;
startTransition();
/* ==================== Transition Initiator ==================== */functionstartTransition() {
clearInterval(transHandler);
targetColor = generateRGB();
distance = calculateDistance(currentColor, targetColor);
increment = calculateIncrement(distance, fps, duration);
transHandler = setInterval(function() {
transition();
}, 1000/fps);
}
/* ==================== Transition Calculator ==================== */functiontransition() {
// checking Rif (currentColor[0] > targetColor[0]) {
currentColor[0] -= increment[0];
if (currentColor[0] <= targetColor[0]) {
increment[0] = 0;
}
} else {
currentColor[0] += increment[0];
if (currentColor[0] >= targetColor[0]) {
increment[0] = 0;
}
}
// checking Gif (currentColor[1] > targetColor[1]) {
currentColor[1] -= increment[1];
if (currentColor[1] <= targetColor[1]) {
increment[1] = 0;
}
} else {
currentColor[1] += increment[1];
if (currentColor[1] >= targetColor[1]) {
increment[1] = 0;
}
}
// checking Bif (currentColor[2] > targetColor[2]) {
currentColor[2] -= increment[2];
if (currentColor[2] <= targetColor[2]) {
increment[2] = 0;
}
} else {
currentColor[2] += increment[2];
if (currentColor[2] >= targetColor[2]) {
increment[2] = 0;
}
}
// applying the new modified color
transElement.style.backgroundColor = rgb2hex(currentColor);
// transition ended. start a new oneif (increment[0] == 0 && increment[1] == 0 && increment[2] == 0) {
startTransition();
}
}
body {
background: white;
}
Solution 2:
Here is another implementation of color transition/animation using pure JavaScript and CSS
constrandomColor = () => '#' + Math.random().toString(16).substr(-6)
constchangeColor = () => document.body.style.backgroundColor = randomColor()
setInterval(() => {
changeColor()
}, 5000)
// start color animation as soon as document is readydocument.onreadystatechange = () => {
if (document.readyState === 'complete') {
changeColor()
}
}
body {
transition: background 5s;
}
Solution 3:
where is too many variables? what about this way?
var el = document.getElementById("sandbox"),
interval = 2000;
functiongetNewColor(){
//generate color
}
functiongetOldColor(el){
//get current color
}
functionswitchColor(el, oldColor, newColor){
//change color
}
setInterval(function(){
swithColors(el, getOldColor(el), getNewColor());
},interval);
Solution 4:
Thanks to akinuri I managed to adapt his answer to a dynamic function that runs on requestanimationframe. Thanks again akinuri, nice code. ps: currentColor and targetColor request a string with the rgb value('rgb(0,0,0)')
functionstartColorFade(fps, duration, element, currentColor, targetColor) {
var stop = false;
var fpsInterval = 1000 / fps;
var now;
var then = Date.now();
var elapsed;
var startTime = then;
var currentColorArray = getElementBG(currentColor);
var targetColorArray = getElementBG(targetColor);
var distance = calculateDistance(currentColorArray, targetColorArray);
var increment = calculateIncrement(distance, fps, duration);
animateColor(duration, element, currentColorArray, targetColorArray, increment, stop, fpsInterval, now, then, elapsed, startTime);
}
functionanimateColor( duration, element, currentColorArray, targetColorArray, increment, stop, fpsInterval, now, then, elapsed, startTime ) {
var step = function() {
if (stop) {
return;
}
// request another framerequestAnimationFrame(function() //arguments can passed on the callback by an anonymous funtion
{
animateColor(duration, element, currentColorArray, targetColorArray, increment, stop, fpsInterval, now, then, elapsed, startTime);
colorTransition(element, currentColorArray, targetColorArray, increment);
});
// calc elapsed time since last loop
now = Date.now();
elapsed = now - then;
// if enough time has elapsed, draw the next frameif (elapsed > fpsInterval) {
// Get ready for next frame by setting then=now, but...// Also, adjust for fpsInterval not being multiple of 16.67
then = now - (elapsed % fpsInterval);
// draw stuff here var sinceStart = now - startTime;
}
if (sinceStart / 1000 * 100 >= duration * 100)
{
stop = true;
}
}
step();
}
functioncolorTransition(element, currentColorArray, targetColorArray, increment) {
// checking Rif (currentColorArray[0] > targetColorArray[0]) {
currentColorArray[0] -= increment[0];
if (currentColorArray[0] <= targetColorArray[0]) {
increment[0] = 0;
}
} else {
currentColorArray[0] += increment[0];
if (currentColorArray[0] >= targetColorArray[0]) {
increment[0] = 0;
}
}
// checking Gif (currentColorArray[1] > targetColorArray[1]) {
currentColorArray[1] -= increment[1];
if (currentColorArray[1] <= targetColorArray[1]) {
increment[1] = 0;
}
} else {
currentColorArray[1] += increment[1];
if (currentColorArray[1] >= targetColorArray[1]) {
increment[1] = 0;
}
}
// checking Bif (currentColorArray[2] > targetColorArray[2]) {
currentColorArray[2] -= increment[2];
if (currentColorArray[2] <= targetColorArray[2]) {
increment[2] = 0;
}
} else {
currentColorArray[2] += increment[2];
if (currentColorArray[2] >= targetColorArray[2]) {
increment[2] = 0;
}
}
// apply the new modified color
element.style.backgroundColor = rgb2hex(currentColorArray);
}
functiongetElementBG(elmBGColor) {
var bg = elmBGColor; // i.e: RGB(255, 0, 0)
bg = bg.match(/\((.*)\)/)[1];
bg = bg.split(",");
for (var i = 0; i < bg.length; i++) {
bg[i] = parseInt(bg[i], 10);
}
if (bg.length > 3) { bg.pop(); }
return bg; // return array
}
functioncalculateDistance(colorArray1, colorArray2) {
var distance = [];
for (var i = 0; i < colorArray1.length; i++) {
distance.push(Math.abs(colorArray1[i] - colorArray2[i]));
}
return distance;
}
functioncalculateIncrement(distanceArray, fps, duration) {
var increment = [];
for (var i = 0; i < distanceArray.length; i++) {
increment.push(Math.abs(Math.floor(distanceArray[i] / (fps * duration))));
if (increment[i] == 0) {
increment[i]++;
}
}
return increment;
}
functionrgb2hex(colorArray) {
var hex = [];
for (var i = 0; i < colorArray.length; i++) {
hex.push(colorArray[i].toString(16));
if (hex[i].length < 2) { hex[i] = "0" + hex[i]; }
}
return"#" + hex.join("");
}
//random rgb values in array, very nicefunctiongenerateRGB(min, max) {
var min = min || 0;
var max = max || 255;
var color = [];
for (var i = 0; i < 3; i++) {
var num = Math.floor(Math.random() * max);
while (num < min) {
num = Math.floor(Math.random() * max);
}
color.push(num);
}
return color;
}
Solution 5:
Use hsl()
For example in ReactJS (here with CoffeeScript) acting on an SVG text element, though the same technique will work with HTML p/span/h1 etc (color instead of fill property):
render: ->
#[... svg setup]
text
x: 50
y: 50
fontSize: 20
fill: "hsl(#{@state.el_hue}, #{@state.el_sat}%, @state.el_lum)%"
"Hello from randomly changing color text."getInitialState: ->
el_hue: 0el_sat: 0el_lum: 0componentDidMount: ->
setInterval =>
@setStateel_hue: Math.random() * 360el_sat: Math.random() * 100el_lum: Math.random() * 100
, 30
# should do crazy things, change color etc
Here I just did random things with the hsl vals every interval, but you can do anything this way. So you can set up a red to blue transition by just altering the hue values appropriately.
Post a Comment for "Continuous Color Transition"