function IncMosaic()
{
// --------------------------------------------------------------------------------------------------------------------
// Members
// --------------------------------------------------------------------------------------------------------------------
// Canvas
this.canvasId;
this.canvas;
this.ctx;
this.imageData;
/// Images
this.pairUrl = [];
this.pairImages = [];
this.imagesLoaded = 0;
this.imageWidth;
this.imageHeight;
// Effect
this.squareCountX;
this.squareCountY;
this.srcSquareWidth;
this.srcSquareHeight;
this.squareWidth;
this.squareHeight;
this.effects = [];
this.squareEffects = [];
// Time
this.startTime;
// --------------------------------------------------------------------------------------------------------------------
// Functions
// --------------------------------------------------------------------------------------------------------------------
this.addPairImages = function(url1, url2)
{
var urls = new IncPairUrl(url1, url2);
this.pairUrl.push(urls);
};
this.start = function(canvasId, squareCountX, squareCountY)
{
// Canvas ID
this.canvasId = canvasId;
// Set square count
this.squareCountX = squareCountX;
this.squareCountY = (squareCountY === undefined) ? squareCountX: squareCountY;
// Init the canvas objects
this.init();
// Register effects
this.registerEffects();
// Set a new effect transition between 2 images
this.SetNewEffect();
// Main loop
this.loopCallback();
};
this.SetNewEffect = function()
{
// Set a random pair images
this.setRandomPairImages();
// Set random effect on the squares
this.setRandomSquareEffect();
// Time
this.startTime = new Date().getTime();
}
this.init = function()
{
// Init canvas objects
this.canvas = document.getElementById(this.canvasId );
this.ctx = this.canvas.getContext('2d');
this.ctx.fillStyle = "#000000";
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
};
this.registerPreNewCanvasSize = function(newCanvasWidth, newCanvasHeight)
{
};
this.registerPostNewCanvasSize = function(newCanvasWidth, newCanvasHeight)
{
// Recalculate the size of the mosaic squares
incMosaic.squareWidth = Math.floor(newCanvasWidth / incMosaic.squareCountX);
incMosaic.squareHeight = Math.floor(newCanvasHeight / incMosaic.squareCountY);
};
this.setRandomPairImages = function()
{
this.imagesLoaded = 0;
var randInd = this.randomInt(0, this.pairUrl.length);
var pairUrl = this.pairUrl[randInd];
this.pairImages.length = 0;
this.pairImages.push(this.getImageFromUrl(pairUrl.imageUrl1));
this.pairImages.push(this.getImageFromUrl(pairUrl.imageUrl2));
};
this.setRandomSquareEffect = function()
{
this.squareEffects.length = 0;
for (var i = 0; i < this.squareCountX; ++i) {
for (var j = 0; j < this.squareCountY; ++j) {
var fullEffect = this.effects[this.randomInt(0, this.effects.length)].copy();
fullEffect.x = i;
fullEffect.y = j;
this.squareEffects.push(fullEffect);
}
}
};
this.loopCallback = function()
{
var self = incMosaic;
if (self.imagesLoaded == 2) {
// Redraw
self.redraw();
}
// Loop
requestAnimationFrame(self.loopCallback);
};
this.redraw = function()
{
// Get time
var time = new Date().getTime();
if (time < this.startTime + 3000) {
// Draw the first image
this.ctx.drawImage(this.pairImages[0], 0, 0, this.srcSquareWidth*this.squareCountX, this.srcSquareHeight*this.squareCountY, 0, 0, this.squareWidth*this.squareCountX, this.squareHeight*this.squareCountY);
return;
}
// Update effects
var effectsContinue = false;
for (var i = 0; i < this.squareEffects.length; ++i) {
// Update
var fullEffect = this.squareEffects[i];
effectsContinue = fullEffect.update(time) || effectsContinue;
for (var j = 0; j < 2; ++j) {
var effectInfo = fullEffect.effectInfos[j];
if (effectInfo !== null) {
// Draw square
this.drawSquare(fullEffect, this.pairImages[j], effectInfo);
}
}
}
if (!effectsContinue) {
console.log("Effect finished !!!!!");
this.SetNewEffect();
}
};
this.drawSquare = function(fullEffect, image, effectInfo)
{
this.ctx.save();
// Global alpha
this.ctx.globalAlpha = effectInfo.alpha;
// Compute src and dest square position
var srcPosX = fullEffect.x * this.srcSquareWidth;
var srcPosY = fullEffect.y * this.srcSquareHeight;
var destPosX = fullEffect.x * this.squareWidth;
var destPosY = fullEffect.y * this.squareHeight;
// Draw colored rectangle
this.ctx.fillStyle = "rgba(" + effectInfo.color.r + "," + effectInfo.color.v + "," + effectInfo.color.b + "," + effectInfo.color.a + ")";
this.ctx.fillRect(destPosX, destPosY, this.squareWidth, this.squareHeight);
// Draw image
this.ctx.drawImage(image, srcPosX, srcPosY, this.srcSquareWidth, this.srcSquareHeight, destPosX, destPosY, this.squareWidth, this.squareHeight);
this.ctx.restore();
};
this.registerEffects = function()
{
var count = 7;
var color = 64;
// Create semi random effects
var range1 = 3000;
var range2 = 5000;
var i, time1, time2, effectParam1, effect1, effectParam2, effect2, fullEffect1;
for (i = 0; i < count; ++i) {
time1 = this.randomInt(range1, range2);
time2 = this.randomInt(range1, range2);
c1 = this.randomInt(0, color);
effectParam1 = new IncEffectParams(new IncColor(c1, c1, c1, 0), new IncAnim(1, time1), 1, new IncAnim(-1, time1));
effect1 = new IncSquareEffect_Alpha(effectParam1, createjs.Ease.quadOut, createjs.Ease.quadOut);
effectParam2 = new IncEffectParams(new IncColor(c1, c1, c1, 1), new IncAnim(0, time2), 0, new IncAnim(1, time2));
effect2 = new IncSquareEffect_Alpha(effectParam2, createjs.Ease.quadIn, createjs.Ease.quadIn, time1 / 2.5);
fullEffect1 = new IncFullEffect(effect1, effect2, time1, time2);
this.effects.push(fullEffect1);
}
// Create semi random effects
range1 = 7000;
range2 = 15000;
for (i = 0; i < count; ++i) {
time1 = this.randomInt(range1, range2);
time2 = this.randomInt(range1, range2);
c1 = this.randomInt(0, color);
effectParam1 = new IncEffectParams(new IncColor(c1, c1, c1, 0), new IncAnim(1, time1), 1, new IncAnim(-1, time1));
effect1 = new IncSquareEffect_Alpha(effectParam1, createjs.Ease.quadOut, createjs.Ease.quadOut);
effectParam2 = new IncEffectParams(new IncColor(c1, c1, c1, 1), new IncAnim(0, time2), 0, new IncAnim(1, time2));
effect2 = new IncSquareEffect_Alpha(effectParam2, createjs.Ease.quadIn, createjs.Ease.quadIn, time1 / 2.5);
fullEffect1 = new IncFullEffect(effect1, effect2, time1, time2);
this.effects.push(fullEffect1);
}
// Create semi random effects
range1 = 17000;
range2 = 23000;
for (i = 0; i < count; ++i) {
time1 = this.randomInt(range1, range2);
time2 = this.randomInt(range1, range2);
c1 = this.randomInt(0, color);
effectParam1 = new IncEffectParams(new IncColor(c1, c1, c1, 0), new IncAnim(1, time1), 1, new IncAnim(-1, time1));
effect1 = new IncSquareEffect_Alpha(effectParam1, createjs.Ease.quadOut, createjs.Ease.quadOut);
effectParam2 = new IncEffectParams(new IncColor(c1, c1, c1, 1), new IncAnim(0, time2), 0, new IncAnim(1, time2));
effect2 = new IncSquareEffect_Alpha(effectParam2, createjs.Ease.quadIn, createjs.Ease.quadIn, time1 / 2.5);
fullEffect1 = new IncFullEffect(effect1, effect2, time1, time2);
this.effects.push(fullEffect1);
}
};
// --------------------------------------------------------------------------------------------------------------------
// Tools
// --------------------------------------------------------------------------------------------------------------------
this.randomInt = function(min, max)
{
return Math.floor(this.randomFloat(min, max));
};
this.randomFloat = function(min, max)
{
return Math.random() * (max - min) + min;
};
this.getImageFromUrl = function(url)
{
var self = incMosaic;
var image = new Image();
image.onload = function() {
// When the first image is loaded we can get the image dimention and init the autoresize of the canvas
if (self.imagesLoaded === 0) {
// Set some image size related vars
self.imageWidth = image.width;
self.imageHeight = image.height;
self.srcSquareWidth = image.width / self.squareCountX;
self.srcSquareHeight = image.height / self.squareCountY;
// Call the resize object
if (incResize !== undefined) {
incResize.resizeElements();
}
}
self.imagesLoaded += 1;
};
image.src = url;
return image;
};
}
function IncPairUrl(url1, url2)
{
this.imageUrl1 = url1;
this.imageUrl2 = url2;
}
// --------------------------------------------------------------------------------------------------------------------
// Effects
// --------------------------------------------------------------------------------------------------------------------
function IncColor(r, v, b, a)
{
this.r = r;
this.v = v;
this.b = b;
this.a = a;
this.copy = function()
{
return new IncColor(this.r, this.v, this.b, this.a);
};
}
function IncAnim(value, time)
{
this.value = value;
this.time = time;
}
function IncEffectInfo()
{
this.color;
this.alpha;
}
function IncEffectParams(color, colorAnim, alpha, alphaAnim)
{
// Color
this.color = color;
this.colorAnim = colorAnim;
// Alpha
this.alpha = alpha;
this.alphaAnim = alphaAnim;
this.computeColorAnimValue = function(elapsedTime, easeFunc)
{
return this.computeAnimValue(this.colorAnim, elapsedTime, easeFunc);
};
this.computeAlphaAnimValue = function(elapsedTime, easeFunc)
{
return this.computeAnimValue(this.alphaAnim, elapsedTime, easeFunc);
};
this.computeAnimValue = function(anim, elapsedTime, easeFunc)
{
// Compute color alpha anim
if (elapsedTime < anim.time) {
return easeFunc(elapsedTime/anim.time) * anim.value;
}
return anim.value;
};
}
function IncSquareEffect_Alpha(effectParms, tweenColorFunc, tweenAlphaFunc, waitTime)
{
// Effect parameters
this.effectParms = effectParms;
// Tween functions
this.tweenColorFunc = tweenColorFunc;
this.tweenAlphaFunc = tweenAlphaFunc;
// Time
this.waitTime = (waitTime!==undefined) ? waitTime : 0;
this.update = function(elapsedTime)
{
var info = new IncEffectInfo();
// Compute new color
var newColorValue = this.effectParms.computeColorAnimValue(elapsedTime, this.tweenColorFunc);
info.color = this.effectParms.color.copy();
info.color.a += newColorValue;
// Compute alpha anim
var newAlphaValue = this.effectParms.computeAlphaAnimValue(elapsedTime, this.tweenAlphaFunc);
info.alpha = this.effectParms.alpha;
info.alpha += newAlphaValue;
return info;
};
}
function IncFullEffect(effect1, effect2, totalTime1, totalTime2)
{
// Position
this.x = 0;
this.y = 0;
// Effect
this.effects = [effect1, effect2];
this.effectInfos = [null, null];
// Time
this.startTime = [0, 0];
this.totalTime = [totalTime1, totalTime2];
this.copy = function()
{
return new IncFullEffect(this.effects[0], this.effects[1], this.totalTime[0], this.totalTime[1]);
};
this.update = function(time)
{
if (this.startTime[0] === 0) {
this.startTime[0] = time;
this.startTime[1] = time;
return true;
}
for (var i = 0; i < 2; ++i) {
// If we are in the good time range we update the effect
var waitTime = this.startTime[i] + this.effects[i].waitTime;
var updateEffect = time < this.totalTime[i] + waitTime;
if (time > waitTime && updateEffect) {
this.effectInfos[i] = this.effects[i].update(time - waitTime);
}
if (i == 1 && !updateEffect) {
// The effect is done
return false;
}
}
return true;
};
}
// --------------------------------------------------------------------------------------------------------------------
// Tools
// --------------------------------------------------------------------------------------------------------------------
window.requestAnimationFrame = (function() {
return window.requestAnimationFrame || // Chromium
window.webkitRequestAnimationFrame || // Webkit
window.mozRequestAnimationFrame || // Mozilla Geko
window.oRequestAnimationFrame || // Opera Presto
window.msRequestAnimationFrame || // IE Trident?
function(callback, element){ // Fallback function
window.setTimeout(callback, 20);
};
})();
var incMosaic = new IncMosaic();