312 lines
9.4 KiB
JavaScript
312 lines
9.4 KiB
JavaScript
// mode : terrain de vie, proximité, superposition....
|
|
// profondeur : atlas, carte
|
|
|
|
let modeAmount = 0,
|
|
curentMode = 1, prevMode,
|
|
currentProfondeur = "atlas",
|
|
colors = {
|
|
bg: {
|
|
h: 29,
|
|
s: 48,
|
|
l: 48
|
|
}
|
|
};
|
|
|
|
document.querySelectorAll('.mode').forEach(function(node, index) {
|
|
modeAmount++;
|
|
node.addEventListener('click', function() {
|
|
document.querySelectorAll('.active').forEach(function(el) {
|
|
el.classList.remove('active');
|
|
if (currentProfondeur == "carte") { el.classList.add('collapsed'); }
|
|
});
|
|
node.classList.toggle('active');
|
|
prevMode = curentMode;
|
|
curentMode = index + 1;
|
|
|
|
if (curentMode != prevMode) {
|
|
changeColors(curentMode - prevMode);
|
|
}
|
|
|
|
})
|
|
});
|
|
|
|
function toggleProfondeur(el) {
|
|
if (el.classList.contains("selected")) {
|
|
return;
|
|
} else {
|
|
for (let sibling of el.parentNode.children) {
|
|
sibling.classList.remove('selected');
|
|
}
|
|
}
|
|
el.classList.add("selected");
|
|
if(el.innerHTML == "L'atlas") {
|
|
currentProfondeur = "atlas";
|
|
document.querySelectorAll('.mode').forEach(function(node) {
|
|
if(node.classList.contains("collapsed")) {
|
|
node.classList.remove("collapsed");
|
|
}
|
|
});
|
|
} else {
|
|
currentProfondeur = "carte";
|
|
document.querySelectorAll('.mode').forEach(function(node) {
|
|
if(!node.classList.contains("active")) {
|
|
node.classList.add("collapsed");
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// onclick sur les flèches du menu
|
|
function toggleMode(direction) {
|
|
let modes = [];
|
|
let currentIndex;
|
|
document.querySelectorAll('.mode').forEach(function(node, index) {
|
|
modes.push(node);
|
|
if (node.classList.contains("active")) {
|
|
currentIndex = index;
|
|
node.classList.remove("active");
|
|
if (currentProfondeur == "carte") {
|
|
node.classList.add("collapsed");
|
|
}
|
|
}
|
|
});
|
|
if (direction == "next" && currentIndex + 2 <= modeAmount) {
|
|
modes[currentIndex + 1].classList.add('active');
|
|
curentMode = curentMode + 1;
|
|
changeColors(1);
|
|
} else if (direction == "prev" && currentIndex - 1 >= 0) {
|
|
modes[currentIndex - 1].classList.add('active');
|
|
curentMode = curentMode - 1;
|
|
changeColors(-1);
|
|
} else if (direction == "next" && currentIndex + 1 == modeAmount) {
|
|
modes[0].classList.add('active');
|
|
curentMode = 1;
|
|
changeColors(-modeAmount + 1);
|
|
} else if (direction == "prev" && currentIndex == 0) {
|
|
modes[modeAmount - 1].classList.add('active');
|
|
curentMode = modeAmount;
|
|
changeColors(modeAmount - 1);
|
|
}
|
|
}
|
|
|
|
|
|
function changeColors(diffAmount) {
|
|
let prevPaletteIndex = (prevMode + (prevMode - 1));
|
|
let baseColors = [];
|
|
baseColors.push(colorPalette[prevPaletteIndex - 1]);
|
|
baseColors.push(colorPalette[prevPaletteIndex]);
|
|
baseColors.push(colorPalette[prevPaletteIndex + 1] ? colorPalette[prevPaletteIndex + 1] : colorPalette[0]);
|
|
|
|
let paletteIndex = (curentMode + (curentMode - 1));
|
|
let targetColors = [];
|
|
|
|
targetColors.push(colorPalette[paletteIndex - 1]);
|
|
targetColors.push(colorPalette[paletteIndex]);
|
|
targetColors.push(colorPalette[paletteIndex + 1 ] ? colorPalette[paletteIndex + 1] : colorPalette[0]);
|
|
|
|
function hexToRgba(color) {
|
|
let colorRgba = {
|
|
r : parseInt(color.substr(0, 2), 16),
|
|
g : parseInt(color.substr(2, 2), 16),
|
|
b : parseInt(color.substr(4, 2), 16),
|
|
a : parseInt(color.substr(6, 2), 16)
|
|
}
|
|
return colorRgba;
|
|
}
|
|
|
|
function rgbaToHex(color) {
|
|
let colorHexa = {
|
|
r : color.r.toString(16).length != 2 ? 0 + color.r.toString(16) : color.r.toString(16),
|
|
g : color.g.toString(16).length != 2 ? 0 + color.g.toString(16) : color.g.toString(16),
|
|
b : color.b.toString(16).length != 2 ? 0 + color.b.toString(16) : color.b.toString(16),
|
|
a : color.a.toString(16).length != 2 ? 0 + color.a.toString(16) : color.a.toString(16)
|
|
}
|
|
return colorHexa.r + colorHexa.g + colorHexa.b + colorHexa.a;
|
|
}
|
|
|
|
let steps = 10, // vitesse de la transition
|
|
currentFrame = 0;
|
|
|
|
function animate() {
|
|
currentFrame++;
|
|
|
|
// à chaque frame on vide currentColors
|
|
// puis pusher trois couleurs hex de transition
|
|
// lorsque le nombre de steps est atteint envoyer les couleurs def
|
|
// et ne pas réanimer
|
|
|
|
currentColors = [];
|
|
for (i = 0; i < baseColors.length; i++) {
|
|
if (currentFrame == steps) {
|
|
currentColors.push(targetColors[i])
|
|
} else {
|
|
currentColors.push(getTransitionColor(baseColors[i], targetColors[i], currentFrame));
|
|
}
|
|
}
|
|
|
|
if (steps == 0) transitionLaunched++;
|
|
if (currentFrame != steps) {
|
|
window.requestAnimationFrame(() => animate());
|
|
} else {
|
|
currentFrame = 0;
|
|
}
|
|
}
|
|
animate()
|
|
|
|
function getTransitionColor(baseColor, targetColor, currentFrame) {
|
|
console.log(baseColor, targetColor, currentFrame)
|
|
let rgbaBase = hexToRgba(baseColor),
|
|
rgbaTarget = hexToRgba(targetColor),
|
|
diff = {
|
|
r : (rgbaBase.r - rgbaTarget.r) * -1,
|
|
g : (rgbaBase.g - rgbaTarget.g) * -1,
|
|
b : (rgbaBase.b - rgbaTarget.b) * -1,
|
|
a : (rgbaBase.a - rgbaTarget.a) * -1
|
|
},
|
|
transitionColor = {
|
|
r : Math.floor(rgbaBase.r + (diff.r / steps) * currentFrame),
|
|
g : Math.floor(rgbaBase.g + (diff.g / steps) * currentFrame),
|
|
b : Math.floor(rgbaBase.b + (diff.b / steps) * currentFrame),
|
|
a : Math.floor(rgbaBase.a + (diff.a / steps) * currentFrame)
|
|
};
|
|
transitionColor = rgbaToHex(transitionColor);
|
|
|
|
return transitionColor;
|
|
}
|
|
}
|
|
|
|
|
|
// COULEURS DE FOND
|
|
// basé sur https://codepen.io/ThreePixDroid/pen/MWeomWp
|
|
|
|
// ajouter un grain fixe : cf
|
|
// https://codepen.io/zadvorsky/pen/PwyoMm
|
|
|
|
let colorPalette = [
|
|
"ff6a0399",
|
|
"c9c4ffff",
|
|
"0796908c",
|
|
"e6ffc4ff",
|
|
"e105054d",
|
|
"aaffa2ff",
|
|
"18b8e64d",
|
|
"ffc4f9ff",
|
|
"9692074d",
|
|
"ffe7c4ff",
|
|
"0629ad4d",
|
|
"fffdbaff"
|
|
]
|
|
|
|
let currentColors = [];
|
|
currentColors.push(
|
|
colorPalette[0],
|
|
colorPalette[1],
|
|
colorPalette[2],
|
|
);
|
|
|
|
class GradientAnimation {
|
|
constructor() {
|
|
this.cnv = document.querySelector('canvas');
|
|
this.ctx = this.cnv.getContext('2d');
|
|
|
|
// réglages du fond
|
|
this.radius = 1800;
|
|
this.speed = 0.001;
|
|
|
|
(window.onresize = () => {
|
|
this.setCanvasSize();
|
|
this.createCircles();
|
|
})();
|
|
this.drawAnimation();
|
|
}
|
|
setCanvasSize() {
|
|
this.w = this.cnv.width = innerWidth * devicePixelRatio;
|
|
this.h = this.cnv.height = innerHeight * devicePixelRatio;
|
|
this.ctx.scale(devicePixelRatio, devicePixelRatio);
|
|
}
|
|
createCircles() {
|
|
this.circles = [];
|
|
// positionnement des cercles directement ici
|
|
this.circles.push(new Circle(this.w, this.h, this.radius, 30, 30, 0));
|
|
this.circles.push(new Circle(this.w, this.h, this.radius, window.innerWidth / 2, window.innerHeight, 1));
|
|
this.circles.push(new Circle(this.w, this.h, this.radius, window.innerWidth - 30, 30, 2));
|
|
}
|
|
drawCircles() {
|
|
this.circles.forEach(circle => circle.draw(this.ctx, this.speed));
|
|
}
|
|
drawBackground() {
|
|
this.ctx.fillStyle = "#aaaaaa";
|
|
this.ctx.fillRect(0, 0, this.w, this.h);
|
|
}
|
|
drawAnimation() {
|
|
this.drawBackground();
|
|
this.drawCircles();
|
|
window.requestAnimationFrame(() => this.drawAnimation());
|
|
}
|
|
}
|
|
|
|
class Circle {
|
|
constructor(w, h, radius, posX, posY, index) {
|
|
this.x = posX;
|
|
this.y = posY;
|
|
this.angle = Math.random() * Math.PI * 2;
|
|
this.radius = radius;
|
|
this.index = index;
|
|
this.firstColor = "#" + currentColors[index];
|
|
this.secondColor = "#ffffff00";
|
|
}
|
|
draw(ctx, speed) {
|
|
this.angle += speed;
|
|
const x = this.x + Math.cos(this.angle) * 200;
|
|
const y = this.y + Math.sin(this.angle) * 200;
|
|
const gradient = ctx.createRadialGradient(x, y, 0, x, y, this.radius);
|
|
gradient.addColorStop(0, "#" + currentColors[this.index]);
|
|
gradient.addColorStop(1, this.secondColor);
|
|
|
|
ctx.globalCompositionOperation = "multiply"; // ça marche pas
|
|
ctx.fillStyle = gradient;
|
|
ctx.beginPath();
|
|
ctx.arc(x, y, this.radius, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
}
|
|
}
|
|
|
|
window.onload = () => {
|
|
new GradientAnimation();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* palette :
|
|
multiply vers blanc
|
|
|
|
0 #ff6a03 45%
|
|
1 TERRAIN DE VIE
|
|
1 #c9c4ff 100%
|
|
|
|
2 #079690 30%
|
|
2 PROXIMITE
|
|
3 #e6ffc4 100%
|
|
|
|
4 #e10505 30%
|
|
3 SUPPERPOSITION
|
|
5 #aaffa2 100%
|
|
|
|
6 #18b8e6 30%
|
|
4 PUISSANCE
|
|
7 #ffc4f9 100%
|
|
|
|
8 #969207 30%
|
|
5 ACTION
|
|
9 #ffe7c4 100%
|
|
|
|
10 #0629ad 30%
|
|
6 DOLEANCER
|
|
11 #fffdba 100% */
|
|
|
|
|
|
// 1 1, 2 3, 3 5, 4 7, 5 9, 6 11
|