.bubble-link { position: absolute; border-radius: 50%; display: flex; align-items: center; justify-content: center; text-align: center; cursor: pointer; transition: transform 0.3s ease, box-shadow 0.3s ease; background: transparent; color: white; font-weight: bold; text-decoration: none; box-shadow: none; z-index: 10; } .bubble-link:hover { transform: scale(1.05); z-index: 100; } .bubble-xlarge { width: 280px; height: 280px; font-size: 26px; } .bubble-large { width: 220px; height: 220px; font-size: 22px; } .bubble-medium { width: 170px; height: 170px; font-size: 18px; } .bubble-small { width: 130px; height: 130px; font-size: 16px; } @media (max-width: 768px) { #bubbles-section { height: 500px; } .bubble-xlarge { width: 160px; height: 160px; font-size: 18px; } .bubble-large { width: 130px; height: 130px; font-size: 16px; } .bubble-medium { width: 110px; height: 110px; font-size: 14px; } .bubble-small { width: 90px; height: 90px; font-size: 12px; } } (function() { // Configuration - MODIFIE TES LIENS ICI const bubblesConfig = [ { text: "Graphisme", url: "/graphisme", size: "xlarge" }, { text: "Produit", url: "/produit", size: "large" }, { text: "Animation", url: "/animation", size: "medium" }, { text: "Dynamisation", url: "/dynamisation", size: "small" }, { text: "Programmation", url: "/programmation", size: "medium" } ]; const canvas = document.getElementById('bubbles-canvas'); const ctx = canvas.getContext('2d'); const container = document.getElementById('bubbles-container'); function resizeCanvas() { canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; } resizeCanvas(); class Bubble { constructor(config, index) { this.text = config.text; this.url = config.url; this.size = config.size; // Tailles différentes selon la config const sizeMap = { 'xlarge': 170, 'large': 110, 'medium': 85, 'small': 65 }; this.radius = sizeMap[config.size] || 85; // Position initiale aléatoire partout sur l'écran const margin = 150; this.x = margin + Math.random() * (canvas.width - margin * 2); this.y = margin + Math.random() * (canvas.height - margin * 2); this.originX = this.x; this.originY = this.y; this.phase = Math.random() * Math.PI * 2; this.time = 0; // Vitesse aléatoire pour chaque bulle this.speedX = (Math.random() - 0.5) * 0.4; this.speedY = (Math.random() - 0.5) * 0.4; this.element = this.createElement(); } createElement() { const div = document.createElement('a'); div.className = `bubble-link bubble-${this.size}`; div.href = this.url; div.textContent = this.text; container.appendChild(div); return div; } update() { this.time += 0.01; // Mouvement libre avec vitesse constante this.x += this.speedX; this.y += this.speedY; // Rebond sur les bords avec marge const margin = this.radius + 20; if (this.x canvas.width - margin) { this.speedX *= -1; this.x = Math.max(margin, Math.min(this.x, canvas.width - margin)); } if (this.y canvas.height - margin) { this.speedY *= -1; this.y = Math.max(margin, Math.min(this.y, canvas.height - margin)); } // Petit mouvement organique additionnel const organicX = Math.sin(this.time + this.phase) * 3; const organicY = Math.cos(this.time * 0.8 + this.phase) * 3; this.element.style.left = (this.x + organicX - this.element.offsetWidth / 2) + 'px'; this.element.style.top = (this.y + organicY - this.element.offsetHeight / 2) + 'px'; } checkCollision(other) { const dx = this.x - other.x; const dy = this.y - other.y; const distance = Math.sqrt(dx * dx + dy * dy); const minDistance = this.radius + other.radius; if (distance new Bubble(config, index) ); function drawMetaballs() { const imageData = ctx.createImageData(canvas.width, canvas.height); const data = imageData.data; const step = 1; for (let y = 0; y < canvas.height; y += step) { for (let x = 0; x 0) { // Réduction du rayon pour effet de fusion plus serré const effectiveRadius = bubble.radius * 0.9; sum += (effectiveRadius * effectiveRadius) / (dist * dist); } } // Seuil augmenté pour réduire la zone de fusion if (sum > 1.1) { for (let dy = 0; dy < step; dy++) { for (let dx = 0; dx < step; dx++) { const idx = ((y + dy) * canvas.width + (x + dx)) * 4; if (idx bubble.update()); // Vérifier les collisions entre toutes les bulles for (let i = 0; i < bubbleObjects.length; i++) { for (let j = i + 1; j { const oldWidth = canvas.width; const oldHeight = canvas.height; resizeCanvas(); // Ajuster les positions proportionnellement bubbleObjects.forEach((bubble) => { bubble.x = (bubble.x / oldWidth) * canvas.width; bubble.y = (bubble.y / oldHeight) * canvas.height; bubble.originX = bubble.x; bubble.originY = bubble.y; }); }); animate(); })();

Mon approche du design se caractérise par le mélange des supports créatif.
Mes expériences sont devenus des bulles créatives qui parfois se mêlent entre elles pour la réalisation d’un projet.

Retour en haut