// 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"); } }); } } function changeColors(diffAmount) { let prevPaletteIndex = (prevMode + (prevMode - 1)); // cf commentaire palette à la fin let baseColors = []; baseColors.push( colorPalette[prevPaletteIndex - 1], colorPalette[prevPaletteIndex], colorPalette[prevPaletteIndex + 1] ? colorPalette[prevPaletteIndex + 1] : colorPalette[0] ); let paletteIndex = (curentMode + (curentMode - 1)); let targetColors = []; targetColors.push( colorPalette[paletteIndex - 1], colorPalette[paletteIndex], 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) { 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.01; // variables du grain this.patternSize = 512; this.patternAlpha = 10; // int between 0 and 255, this.patternPixelDataLength = this.patternSize * this.patternSize * 4; this.patternCanvas; this.patternCtx; this.patternData; this.frame = 0; (window.onresize = () => { this.setCanvasSize(); this.createCircles(); })(); this.initGrain(); 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); } initGrain() { let patternSize = 128; // ça marche pas this.patternSize this.patternCanvas = document.createElement('canvas'); this.patternCanvas.width = patternSize; this.patternCanvas.height = patternSize; this.patternCtx = this.patternCanvas.getContext('2d'); this.patternData = this.patternCtx.createImageData(patternSize, patternSize); let value; for (let i = 0; i < this.patternPixelDataLength; i += 4) { value = (Math.random() * 255) | 0; this.patternData.data[i ] = value; this.patternData.data[i + 1] = value; this.patternData.data[i + 2] = value; this.patternData.data[i + 3] = this.patternAlpha; } this.patternCtx.putImageData(this.patternData, 0, 0); } drawAnimation() { this.drawBackground(); this.drawCircles(); this.ctx.fillStyle = this.ctx.createPattern(this.patternCanvas, 'repeat'); this.ctx.fillRect(0, 0, window.innerWidth, window.innerHeight); 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.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 // curentMode + (curentMode - 1)