freepaper/js/granim.js
2023-12-14 11:32:04 -06:00

1054 lines
32 KiB
JavaScript

/*! Granim v2.0.0 - https://sarcadass.github.io/granim.js */
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
function Granim(options) {
this.getElement(options.element);
this.x1 = 0;
this.y1 = 0;
this.name = options.name || false;
this.elToSetClassOn = options.elToSetClassOn || 'body';
this.direction = options.direction || 'diagonal';
this.customDirection = options.customDirection || {};
this.validateInput('direction');
this.isPausedWhenNotInView = options.isPausedWhenNotInView || false;
this.states = options.states;
this.stateTransitionSpeed = options.stateTransitionSpeed || 1000;
this.previousTimeStamp = null;
this.progress = 0;
this.isPaused = false;
this.isCleared = false;
this.isPausedBecauseNotInView = false;
this.context = this.canvas.getContext('2d');
this.channels = {};
this.channelsIndex = 0;
this.activeState = options.defaultStateName || 'default-state';
this.isChangingState = false;
this.currentColors = [];
this.currentColorsPos = [];
this.activetransitionSpeed = null;
this.eventPolyfill();
this.scrollDebounceThreshold = options.scrollDebounceThreshold || 300;
this.scrollDebounceTimeout = null;
this.isImgLoaded = false;
this.isCanvasInWindowView = false;
this.firstScrollInit = true;
this.animating = false;
this.gradientLength = this.states[this.activeState].gradients[0].length;
if (options.image && options.image.source) {
this.image = {
source: options.image.source,
position: options.image.position || ['center', 'center'],
stretchMode: options.image.stretchMode || false,
blendingMode: options.image.blendingMode || false
};
}
this.events = {
start: new CustomEvent('granim:start'),
end: new CustomEvent('granim:end'),
gradientChange: function(details) {
return new CustomEvent('granim:gradientChange', {
detail: {
isLooping: details.isLooping,
colorsFrom: details.colorsFrom,
colorsTo: details.colorsTo,
activeState: details.activeState
},
bubbles: false,
cancelable: false
});
}
};
this.callbacks = {
onStart: typeof options.onStart === 'function' ? options.onStart : false,
onGradientChange: typeof options.onGradientChange === 'function' ?
options.onGradientChange :
false,
onEnd: typeof options.onEnd === 'function' ? options.onEnd : false
};
this.getDimensions();
this.canvas.setAttribute('width', this.x1);
this.canvas.setAttribute('height', this.y1);
this.setColors();
if (this.image) {
this.validateInput('image');
this.prepareImage();
}
this.pauseWhenNotInViewNameSpace = this.pauseWhenNotInView.bind(this);
this.setSizeAttributesNameSpace = this.setSizeAttributes.bind(this);
this.onResize();
if (this.isPausedWhenNotInView) {
this.onScroll();
} else {
if (!this.image) {
this.refreshColorsAndPos();
this.animation = requestAnimationFrame(this.animateColors.bind(this));
this.animating = true;
}
}
// Callback and Event
if (this.callbacks.onStart) this.callbacks.onStart();
this.canvas.dispatchEvent(this.events.start);
}
Granim.prototype.animateColors = require('./animateColors.js');
Granim.prototype.changeBlendingMode = require('./changeBlendingMode.js');
Granim.prototype.changeDirection = require('./changeDirection.js');
Granim.prototype.changeState = require('./changeState.js');
Granim.prototype.clear = require('./clear.js');
Granim.prototype.convertColorToRgba = require('./convertColorToRgba.js');
Granim.prototype.destroy = require('./destroy.js');
Granim.prototype.eventPolyfill = require('./eventPolyfill.js');
Granim.prototype.getColor = require('./getColor.js');
Granim.prototype.getColorDiff = require('./getColorDiff.js');
Granim.prototype.getColorPos = require('./getColorPos.js');
Granim.prototype.getColorPosDiff = require('./getColorPosDiff.js');
Granim.prototype.getCurrentColors = require('./getCurrentColors.js');
Granim.prototype.getCurrentColorsPos = require('./getCurrentColorsPos.js');
Granim.prototype.getDimensions = require('./getDimensions.js');
Granim.prototype.getElement = require('./getElement.js');
Granim.prototype.getLightness = require('./getLightness.js');
Granim.prototype.makeGradient = require('./makeGradient.js');
Granim.prototype.onResize = require('./onResize.js');
Granim.prototype.onScroll = require('./onScroll.js');
Granim.prototype.pause = require('./pause.js');
Granim.prototype.pauseWhenNotInView = require('./pauseWhenNotInView.js');
Granim.prototype.play = require('./play.js');
Granim.prototype.prepareImage = require('./prepareImage.js');
Granim.prototype.refreshColorsAndPos = require('./refreshColorsAndPos.js');
Granim.prototype.setColors = require('./setColors.js');
Granim.prototype.setDirection = require('./setDirection.js');
Granim.prototype.setSizeAttributes = require('./setSizeAttributes.js');
Granim.prototype.triggerError = require('./triggerError.js');
Granim.prototype.validateInput = require('./validateInput.js');
module.exports = Granim;
},{"./animateColors.js":2,"./changeBlendingMode.js":3,"./changeDirection.js":4,"./changeState.js":5,"./clear.js":6,"./convertColorToRgba.js":7,"./destroy.js":8,"./eventPolyfill.js":9,"./getColor.js":10,"./getColorDiff.js":11,"./getColorPos.js":12,"./getColorPosDiff.js":13,"./getCurrentColors.js":14,"./getCurrentColorsPos.js":15,"./getDimensions.js":16,"./getElement.js":17,"./getLightness.js":18,"./makeGradient.js":19,"./onResize.js":20,"./onScroll.js":21,"./pause.js":22,"./pauseWhenNotInView.js":23,"./play.js":24,"./prepareImage.js":25,"./refreshColorsAndPos.js":26,"./setColors.js":27,"./setDirection.js":28,"./setSizeAttributes.js":29,"./triggerError.js":30,"./validateInput.js":31}],2:[function(require,module,exports){
'use strict';
module.exports = function(timestamp) {
var wasWindowIdled = timestamp - this.previousTimeStamp > 100;
var isLoop = this.states[this.activeState].loop !== undefined ? this.states[this.activeState].loop : true;
var progressPercent, isLooping, nextGradient;
// If tab was inactive then resumed, reset the previous timestamp
if (this.previousTimeStamp === null || wasWindowIdled) {
this.previousTimeStamp = timestamp;
}
// Compute progress and save the timestamp
this.progress = this.progress + (timestamp - this.previousTimeStamp);
progressPercent = (this.progress / this.activetransitionSpeed * 100).toFixed(2);
this.previousTimeStamp = timestamp;
// Set the new gradient colors in a property
this.refreshColorsAndPos(progressPercent);
// Continue the animation or prepare for the next one
if (progressPercent < 100) {
this.animation = requestAnimationFrame(this.animateColors.bind(this));
} else {
// if the current animation index is inferior to the penultimate gradient
// or to the last gradient with the loop mode activated
if (this.channelsIndex < this.states[this.activeState].gradients.length - 2 || isLoop) {
// Set the active transition speed to the active state one after changing state
if (this.isChangingState) {
this.activetransitionSpeed = this.states[this.activeState].transitionSpeed || 5000;
this.isChangingState = false;
}
// Resetting properties
this.previousTimeStamp = null;
this.progress = 0;
this.channelsIndex++;
isLooping = false;
// If it's going to loop or if it's the transition after the loop
if (this.channelsIndex === this.states[this.activeState].gradients.length - 1) {
isLooping = true;
} else if (this.channelsIndex === this.states[this.activeState].gradients.length) {
this.channelsIndex = 0;
}
// Checking the next gradient to send in args of an event and a callback
nextGradient = this.states[this.activeState].gradients[this.channelsIndex + 1] === undefined ?
this.states[this.activeState].gradients[0] :
this.states[this.activeState].gradients[this.channelsIndex + 1];
// Compute the colors for the transition and render a new frame
this.setColors();
this.animation = requestAnimationFrame(this.animateColors.bind(this));
// Callback and Event
if (this.callbacks.onGradientChange) {
this.callbacks.onGradientChange({
isLooping: isLooping,
colorsFrom: this.states[this.activeState].gradients[this.channelsIndex],
colorsTo: nextGradient,
activeState: this.activeState
});
}
this.canvas.dispatchEvent(this.events.gradientChange({
isLooping: isLooping,
colorsFrom: this.states[this.activeState].gradients[this.channelsIndex],
colorsTo: nextGradient,
activeState: this.activeState
}));
// Else if it was the last gradient on the list and the loop mode is off
} else {
cancelAnimationFrame(this.animation);
// Callback and Event
if (this.callbacks.onEnd) this.callbacks.onEnd();
this.canvas.dispatchEvent(new CustomEvent('granim:end'));
}
}
};
},{}],3:[function(require,module,exports){
'use strict';
module.exports = function(newBlendingMode) {
this.context.clearRect(0, 0, this.x1, this.y1);
this.context.globalCompositeOperation =
this.image.blendingMode = newBlendingMode;
this.validateInput('blendingMode');
if (this.isPaused) this.refreshColorsAndPos();
};
},{}],4:[function(require,module,exports){
'use strict';
module.exports = function(newDirection) {
this.context.clearRect(0, 0, this.x1, this.y1);
this.direction = newDirection;
this.validateInput('direction');
if (this.isPaused) this.refreshColorsAndPos();
};
},{}],5:[function(require,module,exports){
'use strict';
module.exports = function(newState) {
var _this = this;
// Prevent transitioning to the same state
if (this.activeState === newState) {
return;
}
// Setting the good properties for the transition
if (!this.isPaused) {
this.isPaused = true;
this.pause();
}
this.channelsIndex = -1;
this.activetransitionSpeed = this.stateTransitionSpeed;
this.activeColorsDiff = [];
this.activeColorsPosDiff = [];
this.activeColors = this.getCurrentColors();
this.activeColorsPos = this.getCurrentColorsPos();
this.progress = 0;
this.previousTimeStamp = null;
this.isChangingState = true;
// Compute the gradient color and pos diff between the last frame gradient
// and the first one of the new state
this.states[newState].gradients[0].forEach(function(gradientColor, i, arr) {
var nextColors = _this.convertColorToRgba(_this.getColor(gradientColor));
var nextColorsPos = _this.getColorPos(gradientColor, i);
var colorDiff = _this.getColorDiff(_this.activeColors[i], nextColors);
var colorPosDiff = _this.getColorPosDiff(_this.activeColorsPos[i], nextColorsPos);
_this.activeColorsDiff.push(colorDiff);
_this.activeColorsPosDiff.push(colorPosDiff);
});
// Start the animation
this.activeState = newState;
this.play();
};
},{}],6:[function(require,module,exports){
'use strict';
module.exports = function() {
if (!this.isPaused) {
cancelAnimationFrame(this.animation);
} else {
this.isPaused = false;
}
this.isCleared = true;
this.context.clearRect(0, 0, this.x1, this.y1);
};
},{}],7:[function(require,module,exports){
'use strict';
var regex = {
hexa: /^#(?:[0-9a-fA-F]{3}){1,2}$/,
rgba: /^rgba\((\d{1,3}), ?(\d{1,3}), ?(\d{1,3}), ?(.?\d{1,3})\)$/,
rgb: /^rgb\((\d{1,3}), ?(\d{1,3}), ?(\d{1,3})\)$/,
hsla: /^hsla\((\d{1,3}), ?(\d{1,3})%, ?(\d{1,3})%, ?(.?\d{1,3})\)$/,
hsl: /^hsl\((\d{1,3}), ?(\d{1,3})%, ?(\d{1,3})%\)$/
}, match;
module.exports = function(color) {
switch(identifyColorType(color)) {
default:
this.triggerError('colorType');
case 'hexa':
return hexToRgba(color);
case 'rgba':
return [
parseInt(match[1], 10),
parseInt(match[2], 10),
parseInt(match[3], 10),
parseFloat(match[4])
];
case 'rgb':
return [
parseInt(match[1], 10),
parseInt(match[2], 10),
parseInt(match[3], 10),
1
];
case 'hsla':
return hslaToRgb(
parseInt(match[1], 10) / 360,
parseInt(match[2], 10) / 100,
parseInt(match[3], 10) / 100,
parseFloat(match[4])
);
case 'hsl':
return hslaToRgb(
parseInt(match[1], 10) / 360,
parseInt(match[2], 10) / 100,
parseInt(match[3], 10) / 100,
1
);
}
};
function identifyColorType(color) {
var colorTypes = Object.keys(regex);
var i = 0;
for (i; i < colorTypes.length; i++) {
match = regex[colorTypes[i]].exec(color);
if (match) return colorTypes[i];
}
return false;
}
function hexToRgba(hex) {
// Expand shorthand form (e.g. '03F') to full form (e.g. '0033FF')
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? [
parseInt(result[1], 16),
parseInt(result[2], 16),
parseInt(result[3], 16),
1
] : null;
}
function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
function hslaToRgb(h, s, l, a) {
var r, g, b, q, p;
if (s === 0) {
r = g = b = l; // achromatic
} else {
q = l < 0.5 ? l * (1 + s) : l + s - l * s;
p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), a];
}
},{}],8:[function(require,module,exports){
'use strict';
module.exports = function() {
this.onResize('removeListeners');
this.onScroll('removeListeners');
this.clear();
};
},{}],9:[function(require,module,exports){
'use strict';
module.exports = function() {
if ( typeof window.CustomEvent === 'function' ) return;
function CustomEvent(event, params) {
params = params || { bubbles: false, cancelable: false, detail: undefined };
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
}
CustomEvent.prototype = window.Event.prototype;
window.CustomEvent = CustomEvent;
};
},{}],10:[function(require,module,exports){
'use strict';
module.exports = function(gradientColor) {
if (typeof gradientColor === 'string') {
return gradientColor;
} else if (typeof gradientColor === 'object' && gradientColor.color) {
return gradientColor.color;
} else {
this.triggerError('gradient.color');
}
};
},{}],11:[function(require,module,exports){
'use strict';
module.exports = function(colorA, colorB) {
var i = 0;
var colorDiff = [];
for (i; i < 4; i++) {
colorDiff.push(colorB[i] - colorA[i]);
}
return colorDiff;
};
},{}],12:[function(require,module,exports){
'use strict';
module.exports = function(gradientColor, i) {
if (typeof gradientColor === 'object' && gradientColor.pos) {
return gradientColor.pos;
} else {
// Ensure first and last position to be 0 and 100
return parseFloat(!i ? 0 : ((1 / (this.gradientLength - 1)) * i).toFixed(2));
}
};
},{}],13:[function(require,module,exports){
'use strict';
module.exports = function(posA, posB) {
return posB - posA;
};
},{}],14:[function(require,module,exports){
'use strict';
module.exports = function() {
var i, j;
var currentColors = [];
for (i = 0; i < this.currentColors.length; i++) {
currentColors.push([]);
for (j = 0; j < 4; j++) {
currentColors[i].push(this.currentColors[i][j]);
}
}
// Return a deep copy of the current colors
return currentColors;
};
},{}],15:[function(require,module,exports){
'use strict';
module.exports = function() {
var currentColorsPos = [], i;
for (i = 0; i < this.currentColorsPos.length; i++) {
currentColorsPos.push(this.currentColorsPos[i]);
}
// Return a deep copy of the current colors
return currentColorsPos;
};
},{}],16:[function(require,module,exports){
'use strict';
module.exports = function() {
this.x1 = this.canvas.offsetWidth;
this.y1 = this.canvas.offsetHeight;
};
},{}],17:[function(require,module,exports){
'use strict';
module.exports = function(element) {
if (element instanceof HTMLCanvasElement) {
this.canvas = element;
} else if (typeof element === 'string') {
this.canvas = document.querySelector(element);
} else {
throw new Error('The element you used is neither a String, nor a HTMLCanvasElement');
}
if (!this.canvas) {
throw new Error('`' + element + '` could not be found in the DOM');
}
};
},{}],18:[function(require,module,exports){
'use strict';
module.exports = function() {
var currentColors = this.getCurrentColors();
var gradientAverage = null;
var lightnessAverage, i;
var colorsAverage = currentColors.map(function(el) {
// Compute the average lightness of each color
// in the current gradient
return Math.max(el[0], el[1], el[2]);
});
for (i = 0; i < colorsAverage.length; i++) {
// Add all the average lightness of each color
gradientAverage = gradientAverage === null ?
colorsAverage[i] : gradientAverage + colorsAverage[i];
if (i === colorsAverage.length - 1) {
// if it's the last lightness average
// divide it by the total length to
// have the global average lightness
lightnessAverage = Math.round(gradientAverage / (i + 1));
}
}
return lightnessAverage >= 128 ? 'light' : 'dark';
};
},{}],19:[function(require,module,exports){
'use strict';
module.exports = function() {
var gradient = this.setDirection();
var elToSetClassOnClass = document.querySelector(this.elToSetClassOn).classList;
var i = 0;
this.context.clearRect(0, 0, this.x1, this.y1);
if (this.image) {
this.context.drawImage(
this.imageNode,
this.imagePosition.x,
this.imagePosition.y,
this.imagePosition.width,
this.imagePosition.height
);
}
for (i; i < this.currentColors.length; i++) {
gradient.addColorStop(this.currentColorsPos[i], 'rgba(' +
this.currentColors[i][0] + ', ' +
this.currentColors[i][1] + ', ' +
this.currentColors[i][2] + ', ' +
this.currentColors[i][3] + ')'
);
}
if (this.name) {
if (this.getLightness() === 'light') {
elToSetClassOnClass.remove(this.name + '-dark');
elToSetClassOnClass.add(this.name + '-light');
} else {
elToSetClassOnClass.remove(this.name + '-light');
elToSetClassOnClass.add(this.name + '-dark');
}
}
this.context.fillStyle = gradient;
this.context.fillRect(0, 0, this.x1, this.y1);
};
},{}],20:[function(require,module,exports){
'use strict';
module.exports = function(type) {
if (type === 'removeListeners') {
window.removeEventListener('resize', this.setSizeAttributesNameSpace);
return;
}
window.addEventListener('resize', this.setSizeAttributesNameSpace);
};
},{}],21:[function(require,module,exports){
'use strict';
module.exports = function(type) {
if (type === 'removeListeners') {
window.removeEventListener('scroll', this.pauseWhenNotInViewNameSpace);
return;
}
window.addEventListener('scroll', this.pauseWhenNotInViewNameSpace);
this.pauseWhenNotInViewNameSpace();
};
},{}],22:[function(require,module,exports){
'use strict';
module.exports = function(state) {
var isPausedBecauseNotInView = state === 'isPausedBecauseNotInView';
if (this.isCleared) return;
if (!isPausedBecauseNotInView) this.isPaused = true;
cancelAnimationFrame(this.animation);
this.animating = false;
};
},{}],23:[function(require,module,exports){
'use strict';
module.exports = function() {
var _this = this;
if (this.scrollDebounceTimeout) clearTimeout(this.scrollDebounceTimeout);
this.scrollDebounceTimeout = setTimeout(function() {
var elPos = _this.canvas.getBoundingClientRect();
_this.isCanvasInWindowView = !(elPos.bottom < 0 || elPos.right < 0 ||
elPos.left > window.innerWidth || elPos.top > window.innerHeight);
if (_this.isCanvasInWindowView) {
if (!_this.isPaused || _this.firstScrollInit) {
if (_this.image && !_this.isImgLoaded) {return;}
_this.isPausedBecauseNotInView = false;
_this.play('isPlayedBecauseInView');
_this.firstScrollInit = false;
}
} else {
if (!_this.image && _this.firstScrollInit) {
_this.refreshColorsAndPos();
_this.firstScrollInit = false;
}
if (!_this.isPaused && !_this.isPausedBecauseNotInView) {
_this.isPausedBecauseNotInView = true;
_this.pause('isPausedBecauseNotInView');
}
}
}, this.scrollDebounceThreshold);
};
},{}],24:[function(require,module,exports){
'use strict';
module.exports = function(state) {
var isPlayedBecauseInView = state === 'isPlayedBecauseInView';
if (!isPlayedBecauseInView) this.isPaused = false;
this.isCleared = false;
if (!this.animating) {
this.animation = requestAnimationFrame(this.animateColors.bind(this));
this.animating = true;
}
};
},{}],25:[function(require,module,exports){
'use strict';
module.exports = function() {
var _this = this;
if (!this.imagePosition) {
this.imagePosition = { x: 0, y: 0, width: 0, height: 0 };
}
if (this.image.blendingMode) {
this.context.globalCompositeOperation = this.image.blendingMode;
}
if (this.imageNode) {
setImagePosition();
return;
}
this.imageNode = new Image();
this.imageNode.onerror = function() {
throw new Error('Granim: The image source is invalid.');
};
this.imageNode.onload = function() {
_this.imgOriginalWidth = _this.imageNode.width;
_this.imgOriginalHeight = _this.imageNode.height;
setImagePosition();
_this.refreshColorsAndPos();
if (!_this.isPausedWhenNotInView || _this.isCanvasInWindowView) {
_this.animation = requestAnimationFrame(_this.animateColors.bind(_this));
}
_this.isImgLoaded = true;
};
this.imageNode.src = this.image.source;
function setImagePosition() {
var i, currentAxis;
for (i = 0; i < 2; i++) {
currentAxis = !i ? 'x' : 'y';
setImageAxisPosition(currentAxis);
}
function setImageAxisPosition(axis) {
var canvasWidthOrHeight = _this[axis + '1'];
var imgOriginalWidthOrHeight = _this[axis === 'x' ? 'imgOriginalWidth' : 'imgOriginalHeight'];
var imageAlignIndex = axis === 'x' ? _this.image.position[0] : _this.image.position[1];
var imageAxisPosition;
switch(imageAlignIndex) {
case 'center':
imageAxisPosition = imgOriginalWidthOrHeight > canvasWidthOrHeight
? -(imgOriginalWidthOrHeight - canvasWidthOrHeight) / 2
: (canvasWidthOrHeight - imgOriginalWidthOrHeight) / 2;
_this.imagePosition[axis] = imageAxisPosition;
_this.imagePosition[axis === 'x' ? 'width' : 'height'] = imgOriginalWidthOrHeight;
break;
case 'top':
_this.imagePosition['y'] = 0;
_this.imagePosition['height'] = imgOriginalWidthOrHeight;
break;
case 'bottom':
_this.imagePosition['y'] = canvasWidthOrHeight - imgOriginalWidthOrHeight;
_this.imagePosition['height'] = imgOriginalWidthOrHeight;
break;
case 'right':
_this.imagePosition['x'] = canvasWidthOrHeight - imgOriginalWidthOrHeight;
_this.imagePosition['width'] = imgOriginalWidthOrHeight;
break;
case 'left':
_this.imagePosition['x'] = 0;
_this.imagePosition['width'] = imgOriginalWidthOrHeight;
break;
}
if (_this.image.stretchMode) {
imageAlignIndex = axis === 'x' ? _this.image.stretchMode[0] : _this.image.stretchMode[1];
switch(imageAlignIndex) {
case 'none':
break;
case 'stretch':
_this.imagePosition[axis] = 0;
_this.imagePosition[axis === 'x' ? 'width' : 'height'] = canvasWidthOrHeight;
break;
case 'stretch-if-bigger':
if (imgOriginalWidthOrHeight < canvasWidthOrHeight) break;
_this.imagePosition[axis] = 0;
_this.imagePosition[axis === 'x' ? 'width' : 'height'] = canvasWidthOrHeight;
break;
case 'stretch-if-smaller':
if (imgOriginalWidthOrHeight > canvasWidthOrHeight) break;
_this.imagePosition[axis] = 0;
_this.imagePosition[axis === 'x' ? 'width' : 'height'] = canvasWidthOrHeight;
break;
}
}
}
}
};
},{}],26:[function(require,module,exports){
'use strict';
module.exports = function(progressPercent) {
var _this = this, activeChannel, activeChannelPos, i, j;
// Loop through each colors of the active gradient
for (i = 0; i < this.activeColors.length; i++) {
// Generate RGBA colors
for (j = 0; j < 4; j++) {
// If color value [0-255] round to the integer,
// Else if opacity [0-1] round to 2 decimals
activeChannel = _this.activeColors[i][j] +
(j !== 3
? Math.ceil(_this.activeColorsDiff[i][j] / 100 * progressPercent)
: Math.round((_this.activeColorsDiff[i][j] / 100 * progressPercent) * 100) / 100
);
// Prevent colors values from going < 0 & > 255
if (activeChannel <= 255 && activeChannel >= 0) {
_this.currentColors[i][j] = activeChannel;
}
}
// Generate gradient color position
activeChannelPos = parseFloat((_this.activeColorsPos[i] +
(_this.activeColorsPosDiff[i] / 100 * progressPercent)
).toFixed(4));
if (activeChannelPos <= 1 && activeChannelPos >= 0) {
_this.currentColorsPos[i] = activeChannelPos;
}
}
this.makeGradient();
};
},{}],27:[function(require,module,exports){
'use strict';
module.exports = function() {
var _this = this, colorDiff, colorPosDiff, nextColors, nextColorsPos;
if (!this.channels[this.activeState]) this.channels[this.activeState] = [];
// If the actual channel exist, reassign properties and exit
// (each channel is saved to prevent recomputing it each time)
if (this.channels[this.activeState][this.channelsIndex] !== undefined) {
this.activeColors = this.channels[this.activeState][this.channelsIndex].colors;
this.activeColorsDiff = this.channels[this.activeState][this.channelsIndex].colorsDiff;
this.activeColorsPos = this.channels[this.activeState][this.channelsIndex].colorsPos;
this.activeColorsPosDiff = this.channels[this.activeState][this.channelsIndex].colorsPosDiff;
return;
}
// Set blank properties
this.channels[this.activeState].push([{}]);
this.channels[this.activeState][this.channelsIndex].colors = [];
this.channels[this.activeState][this.channelsIndex].colorsDiff = [];
this.channels[this.activeState][this.channelsIndex].colorsPos = [];
this.channels[this.activeState][this.channelsIndex].colorsPosDiff = [];
this.activeColors = [];
this.activeColorsDiff = [];
this.activeColorsPos = [];
this.activeColorsPosDiff = [];
// Go on each gradient of the current state
this.states[this.activeState].gradients[this.channelsIndex].forEach(function(color, i) {
// Push the hex color converted to rgba on the channel and the active color properties
var colorPos = _this.getColorPos(color, i);
var color = _this.getColor(color);
var rgbaColor = _this.convertColorToRgba(color);
var activeChannel = _this.channels[_this.activeState];
activeChannel[_this.channelsIndex].colors.push(rgbaColor);
_this.activeColors.push(rgbaColor);
activeChannel[_this.channelsIndex].colorsPos.push(colorPos);
_this.activeColorsPos.push(colorPos);
// If it's the first channel to be set, set the currentColors
if (!_this.isCurrentColorsSet) {
_this.currentColors.push(_this.convertColorToRgba(color));
_this.currentColorsPos.push(colorPos);
}
// If it's the last gradient, compute the color diff between the last gradient and the first one,
// else between the penultimate one and the last one
if (_this.channelsIndex === _this.states[_this.activeState].gradients.length - 1) {
colorDiff = _this.getColorDiff(
activeChannel[_this.channelsIndex].colors[i],
activeChannel[0].colors[i]
);
colorPosDiff = _this.getColorPosDiff(
activeChannel[_this.channelsIndex].colorsPos[i],
activeChannel[0].colorsPos[i]
);
} else {
nextColors = _this.convertColorToRgba(_this.getColor(_this.states[_this.activeState].gradients[_this.channelsIndex + 1][i]));
nextColorsPos = _this.getColorPos(_this.states[_this.activeState].gradients[_this.channelsIndex + 1][i], i);
colorDiff = _this.getColorDiff(activeChannel[_this.channelsIndex].colors[i], nextColors);
colorPosDiff = _this.getColorPosDiff(activeChannel[_this.channelsIndex].colorsPos[i], nextColorsPos);
}
activeChannel[_this.channelsIndex].colorsDiff.push(colorDiff);
_this.activeColorsDiff.push(colorDiff);
activeChannel[_this.channelsIndex].colorsPosDiff.push(colorPosDiff);
_this.activeColorsPosDiff.push(colorPosDiff);
});
this.activetransitionSpeed = this.states[this.activeState].transitionSpeed || 5000;
this.isCurrentColorsSet = true;
};
},{}],28:[function(require,module,exports){
'use strict';
module.exports = function() {
var ctx = this.context;
switch(this.direction) {
case 'diagonal':
return ctx.createLinearGradient(0, 0, this.x1, this.y1);
case 'left-right':
return ctx.createLinearGradient(0, 0, this.x1, 0);
case 'top-bottom':
return ctx.createLinearGradient(this.x1 / 2, 0, this.x1 / 2, this.y1);
case 'radial':
return ctx.createRadialGradient(this.x1 / 2, this.y1 / 2, this.x1 / 2, this.x1 / 2, this.y1 / 2, 0);
case 'custom':
return ctx.createLinearGradient(
getCustomCoordinateInPixels(this.customDirection.x0, this.x1),
getCustomCoordinateInPixels(this.customDirection.y0, this.y1),
getCustomCoordinateInPixels(this.customDirection.x1, this.x1),
getCustomCoordinateInPixels(this.customDirection.y1, this.y1)
);
}
};
function getCustomCoordinateInPixels(coordinate, size) {
return coordinate.indexOf('%') > -1
? size / 100 * parseInt(coordinate.split('%')[0], 10)
: parseInt(coordinate.split('px')[0], 10);
}
},{}],29:[function(require,module,exports){
'use strict';
module.exports = function() {
this.getDimensions();
this.canvas.setAttribute('width', this.x1);
this.canvas.setAttribute('height', this.y1);
if (this.image) this.prepareImage();
this.refreshColorsAndPos();
};
},{}],30:[function(require,module,exports){
'use strict';
module.exports = function(element) {
var siteURL = 'https://sarcadass.github.io/granim.js/api.html';
throw new Error('Granim: Input error on "' + element + '" option.\nCheck the API ' + siteURL + '.');
};
},{}],31:[function(require,module,exports){
'use strict';
module.exports = function(inputType) {
var xPositionValues = ['left', 'center', 'right'];
var yPositionValues = ['top', 'center', 'bottom'];
var stretchModeValues = ['none', 'stretch', 'stretch-if-smaller', 'stretch-if-bigger'];
var blendingModeValues = ['multiply', 'screen', 'normal', 'overlay', 'darken',
'lighten', 'lighter', 'color-dodge', 'color-burn', 'hard-light', 'soft-light',
'difference', 'exclusion', 'hue', 'saturation', 'color', 'luminosity'];
var directionValues = ['diagonal', 'left-right', 'top-bottom', 'radial', 'custom'];
switch(inputType) {
case 'image':
// Validate image.position
if ((!Array.isArray(this.image.position) || this.image.position.length !== 2) ||
xPositionValues.indexOf(this.image.position[0]) === -1 ||
yPositionValues.indexOf(this.image.position[1]) === -1
) { this.triggerError('image.position'); }
// Validate image.stretchMode
if (this.image.stretchMode) {
if ((!Array.isArray(this.image.stretchMode) || this.image.stretchMode.length !== 2) ||
stretchModeValues.indexOf(this.image.stretchMode[0]) === -1 ||
stretchModeValues.indexOf(this.image.stretchMode[1]) === -1
) { this.triggerError('image.stretchMode'); }
}
break;
case 'blendingMode':
if (blendingModeValues.indexOf(this.image.blendingMode) === -1) {
this.clear();
this.triggerError('blendingMode');
}
break;
case 'direction':
if (directionValues.indexOf(this.direction) === -1) {
this.triggerError('direction');
} else {
if (this.direction === 'custom') {
if (!areDefinedInPixelsOrPercentage([
this.customDirection.x0,
this.customDirection.x1,
this.customDirection.y0,
this.customDirection.y1
])) {
this.triggerError('customDirection');
}
}
}
break;
}
};
function areDefinedInPixelsOrPercentage(array) {
var definedInPixelsOrPercentage = true, i = 0, value;
while (definedInPixelsOrPercentage && i < array.length) {
value = array[i];
if (typeof value !== 'string') {
definedInPixelsOrPercentage = false;
} else {
var splittedValue = null;
var unit = null;
if (value.indexOf('px') !== -1) unit = 'px';
if (value.indexOf('%') !== -1) unit = '%';
splittedValue = value.split(unit).filter(function(value) {
return value.length > 0;
});
// Check if there is a unit ('px' or '%'),
// a char before the unit,
// no char after the unit,
// the string without the unit is only composed of digits
if (
!unit
|| splittedValue.length > 2
|| !splittedValue[0]
|| splittedValue[1]
|| !/^-?\d+\.?\d*$/.test(splittedValue[0])
) {
definedInPixelsOrPercentage = false;
}
}
i++;
}
return definedInPixelsOrPercentage;
}
},{}],32:[function(require,module,exports){
window.Granim = require('./lib/Granim.js');
},{"./lib/Granim.js":1}]},{},[32]);