Skip to content Skip to sidebar Skip to footer

Continuous Color Transition

I'm trying to create a continuous color transition like the one in Windows 8 installation, We're getting your PC ready. I couldn't figure out how to write the shift function. Check

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"