bootle / index.html
sm08th's picture
Utilise une couleur plus brillante pour les particules et change les contours en en style néon - Follow Up Deployment
d3db4a7 verified
Raw History Blame Contribute Delete
25.1 kB
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Présentation Cinématique de Bouteille 3D</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/loaders/GLTFLoader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.11.4/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.11.4/dist/ScrollTrigger.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/aos@2.3.4/dist/aos.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Bebas+Neue&display=swap" rel="stylesheet">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Orbitron', sans-serif;
background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);
color: white;
overflow-x: hidden;
position: relative;
}
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background:
radial-gradient(circle at 20% 30%, rgba(255,0,150,0.1) 0%, transparent 30%),
radial-gradient(circle at 80% 70%, rgba(0,200,255,0.1) 0%, transparent 30%);
z-index: 0;
animation: pulse 15s infinite alternate;
}
@keyframes pulse {
0% { opacity: 0.5; }
100% { opacity: 1; }
}
#canvas-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
z-index: 1;
pointer-events: none;
}
.scene {
min-height: 100vh;
width: 100%;
position: relative;
z-index: 2;
display: flex;
flex-direction: column;
justify-content: center;
padding: 0 10%;
opacity: 0;
transition: opacity 0.5s;
}
.scene.active {
opacity: 1;
}
h1 {
font-family: 'Bebas Neue', sans-serif;
font-size: 5rem;
margin-bottom: 2rem;
text-transform: uppercase;
letter-spacing: 3px;
}
p {
font-size: 1.2rem;
max-width: 600px;
line-height: 1.6;
margin-bottom: 2rem;
}
.info-card {
background: rgba(17, 17, 17, 0.8);
border-radius: 10px;
padding: 2rem;
max-width: 400px;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
transform: translateY(50px);
opacity: 0;
transition: all 0.5s;
}
.info-card.visible {
transform: translateY(0);
opacity: 1;
}
.cta-button {
background: linear-gradient(45deg, #ff3366, #ba2650);
color: white;
border: none;
padding: 15px 40px;
font-size: 1.2rem;
border-radius: 30px;
cursor: pointer;
font-family: 'Orbitron', sans-serif;
text-transform: uppercase;
letter-spacing: 2px;
transition: all 0.3s;
margin-top: 2rem;
}
.cta-button:hover {
transform: translateY(-3px);
box-shadow: 0 10px 20px rgba(255, 51, 102, 0.3);
}
/* Header Styles */
header {
position: fixed;
top: 0;
left: 0;
width: 100%;
display: flex;
justify-content: space-between;
padding: 1.5rem 2rem;
z-index: 100;
}
.nav-title {
transform: translateX(-100%);
opacity: 0;
transition: all 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
.nav-title.visible {
transform: translateX(0);
opacity: 1;
}
.nav-toggle {
display: none;
flex-direction: column;
justify-content: space-between;
width: 30px;
height: 21px;
cursor: pointer;
z-index: 101;
transform: translateX(100%);
opacity: 0;
transition: all 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
.nav-toggle.visible {
transform: translateX(0);
opacity: 1;
}
.nav-toggle span {
display: block;
height: 3px;
width: 100%;
background: white;
transition: all 0.3s;
}
.main-nav {
transform: translateX(-100%);
position: fixed;
top: 0;
left: 0;
width: 300px;
height: 100vh;
background: rgba(0, 0, 0, 0.9);
padding: 6rem 2rem;
transition: transform 0.5s cubic-bezier(0.77, 0.2, 0.05, 1.0);
z-index: 99;
}
.main-nav.active {
transform: translateX(0);
}
.nav-title {
font-family: 'Bebas Neue', sans-serif;
font-size: 2rem;
margin-bottom: 2rem;
color: white;
}
.main-nav ul {
list-style: none;
}
.main-nav li {
margin-bottom: 1.5rem;
}
.main-nav a {
color: white;
text-decoration: none;
font-size: 1.2rem;
transition: color 0.3s;
}
.main-nav a:hover {
color: #ff3366;
}
.user-nav {
transform: translateX(100%);
position: fixed;
top: 0;
right: 0;
width: 200px;
height: 100vh;
background: rgba(0, 0, 0, 0.9);
padding: 6rem 2rem;
transition: transform 0.5s cubic-bezier(0.77, 0.2, 0.05, 1.0);
z-index: 99;
}
.user-nav.active {
transform: translateX(0);
}
.user-nav a {
display: block;
color: white;
text-decoration: none;
font-size: 1.2rem;
margin-bottom: 1.5rem;
transition: color 0.3s;
}
.user-nav a:hover {
color: #ff3366;
}
@media (max-width: 768px) {
h1 {
font-size: 3rem;
}
p {
font-size: 1rem;
}
.info-card {
padding: 1.5rem;
}
}
</style>
</head>
<body>
<header>
<h2 class="nav-title">Bouteille 3D</h2>
<div class="nav-toggle">
<span></span>
<span></span>
<span></span>
</div>
<nav class="main-nav">
<ul>
<li><a href="#">Accueil</a></li>
<li><a href="#">Fonctionnalités</a></li>
<li><a href="#">Technologie</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
<div class="user-nav">
<a href="#">Connexion</a>
<a href="#">Inscription</a>
</div>
</header>
<div id="canvas-container"></div>
<section class="scene" id="scene1">
<div class="info-card">
<h1>L'Élégance Redéfinie</h1>
<p>Découvrez notre nouvelle bouteille révolutionnaire, conçue pour capturer la lumière et l'attention.</p>
</div>
</section>
<section class="scene" id="scene2">
<div class="info-card">
<h1>Design Ergonomique</h1>
<p>Une forme étudiée pour un confort inégalé, avec des courbes qui épousent parfaitement votre main.</p>
</div>
</section>
<section class="scene" id="scene3">
<div class="info-card">
<h1>Précision Technique</h1>
<p>Chaque détail est pensé pour optimiser l'expérience utilisateur, de l'ouverture à la fermeture.</p>
</div>
</section>
<section class="scene" id="scene4">
<div class="info-card">
<h1>Système d'Ouverture</h1>
<p>Notre mécanisme breveté offre une ouverture fluide et sécurisée en un seul geste.</p>
</div>
</section>
<section class="scene" id="scene5">
<div class="info-card">
<h1>Technologie Intérieure</h1>
<p>Un système de conservation révolutionnaire maintient la qualité du contenu comme jamais auparavant.</p>
</div>
</section>
<section class="scene" id="scene6">
<div class="info-card">
<h1>Disponible Maintenant</h1>
<p>Commandez dès aujourd'hui et faites l'expérience de l'innovation dans votre quotidien.</p>
<button class="cta-button">Découvrir</button>
</div>
</section>
<script>
// Initialisation Three.js
let scene, camera, renderer, bottle, mixer, particles, particlePositions, particleSystem;
const particleCount = 1000;
// Logo position definitions
const logos = {
default: Array(particleCount).fill().map(() => {
const radius = 3 + Math.random() * 2;
const theta = Math.random() * Math.PI * 2;
const phi = Math.random() * Math.PI;
return new THREE.Vector3(
radius * Math.sin(phi) * Math.cos(theta),
radius * Math.cos(phi),
radius * Math.sin(phi) * Math.sin(theta)
);
}),
logo1: Array(particleCount).fill().map(() => {
// Heart shape
const t = Math.random() * Math.PI * 2;
const x = 2.5 * Math.pow(Math.sin(t), 3);
const y = 2 * Math.cos(t) - 0.8 * Math.cos(2*t) - 0.2 * Math.cos(3*t) - 0.1 * Math.cos(4*t);
const z = (Math.random() - 0.5) * 0.5;
return new THREE.Vector3(x, y, z);
}),
logo2: Array(particleCount).fill().map(() => {
// Spiral
const t = Math.random() * Math.PI * 8;
const r = 0.5 + Math.random() * 0.5;
return new THREE.Vector3(
r * Math.cos(t),
t / 8 - 2,
r * Math.sin(t)
);
}),
logo3: Array(particleCount).fill().map(() => {
// Sphere
const radius = 2;
const theta = Math.random() * Math.PI * 2;
const phi = Math.random() * Math.PI;
return new THREE.Vector3(
radius * Math.sin(phi) * Math.cos(theta),
radius * Math.cos(phi),
radius * Math.sin(phi) * Math.sin(theta)
);
}),
logo4: Array(particleCount).fill().map(() => {
// Cube
const size = 2;
return new THREE.Vector3(
(Math.random() - 0.5) * size,
(Math.random() - 0.5) * size,
(Math.random() - 0.5) * size
);
}),
logo5: Array(particleCount).fill().map(() => {
// Text "3D"
const x = (Math.random() - 0.5) * 4;
const y = (Math.random() - 0.5) * 2;
let z = (Math.random() - 0.5) * 0.5;
if (Math.abs(x) < 1 && Math.abs(y) < 0.8) {
z = (Math.random() - 0.5) * 2;
}
return new THREE.Vector3(x, y, z);
})
};
function initThreeJS() {
// Création de la scène
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000);
// Create particle system
const particleGeometry = new THREE.BufferGeometry();
particlePositions = new Float32Array(particleCount * 3);
// Initialize with default positions
for (let i = 0; i < particleCount; i++) {
const pos = logos.default[i];
particlePositions[i * 3] = pos.x;
particlePositions[i * 3 + 1] = pos.y;
particlePositions[i * 3 + 2] = pos.z;
}
particleGeometry.setAttribute('position', new THREE.BufferAttribute(particlePositions, 3));
// Create particle material with neon effect
const particleMaterial = new THREE.PointsMaterial({
color: 0x00ffff,
size: 0.03,
sizeAttenuation: true,
transparent: true,
opacity: 0.9,
blending: THREE.AdditiveBlending,
alphaMap: createStarAlphaMap(),
map: createStarTexture(),
emissive: 0x00ffff,
emissiveIntensity: 1.5,
fog: true
});
// Create star-shaped texture
function createStarTexture() {
const canvas = document.createElement('canvas');
canvas.width = canvas.height = 64;
const ctx = canvas.getContext('2d');
// Draw neon star shape
ctx.beginPath();
ctx.arc(32, 32, 28, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(0, 255, 255, 0.95)';
ctx.fill();
// Add neon glow effect
const gradient = ctx.createRadialGradient(32, 32, 0, 32, 32, 28);
gradient.addColorStop(0, 'rgba(0, 255, 255, 1)');
gradient.addColorStop(0.5, 'rgba(0, 200, 255, 0.8)');
gradient.addColorStop(0.8, 'rgba(0, 150, 255, 0.3)');
gradient.addColorStop(1, 'rgba(0, 100, 255, 0)');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 64, 64);
// Add outer glow
const outerGlow = ctx.createRadialGradient(32, 32, 20, 32, 32, 32);
outerGlow.addColorStop(0, 'rgba(0, 200, 255, 0.5)');
outerGlow.addColorStop(1, 'rgba(0, 100, 200, 0)');
ctx.fillStyle = outerGlow;
ctx.fillRect(0, 0, 64, 64);
const texture = new THREE.CanvasTexture(canvas);
return texture;
}
function createStarAlphaMap() {
const canvas = document.createElement('canvas');
canvas.width = canvas.height = 64;
const ctx = canvas.getContext('2d');
// Create alpha map for smooth edges
const gradient = ctx.createRadialGradient(32, 32, 0, 32, 32, 24);
gradient.addColorStop(0, 'rgba(255, 255, 255, 1)');
gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 64, 64);
const texture = new THREE.CanvasTexture(canvas);
return texture;
}
// Create particle system
particleSystem = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particleSystem);
// Configuration de la caméra
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
// Configuration du rendu
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('canvas-container').appendChild(renderer.domElement);
// Ajout de lumières
const ambientLight = new THREE.AmbientLight(0x333333);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffeecc, 0.4);
directionalLight.position.set(1, 1, 1);
scene.add(directionalLight);
const pointLight = new THREE.PointLight(0x4488ff, 0.8, 15);
pointLight.position.set(2, 2, 2);
scene.add(pointLight);
const fillLight = new THREE.HemisphereLight(0x446688, 0x223344, 0.2);
scene.add(fillLight);
// Création d'une bouteille temporaire (en attendant le modèle GLB)
createTemporaryBottle();
// Gestion du redimensionnement
window.addEventListener('resize', onWindowResize);
}
function createTemporaryBottle() {
// Géométrie temporaire pour la démo
const geometry = new THREE.CylinderGeometry(0.5, 0.3, 1.5, 64);
const material = new THREE.MeshPhongMaterial({
color: 0x00ffff,
transparent: true,
opacity: 0.9,
shininess: 100,
specular: 0xffffff,
emissive: 0x006666,
emissiveIntensity: 0.3
});
bottle = new THREE.Mesh(geometry, material);
scene.add(bottle);
// Animation du bouchon (sera remplacé par le modèle GLB)
const capGeometry = new THREE.CylinderGeometry(0.2, 0.2, 0.2, 32);
const capMaterial = new THREE.MeshPhongMaterial({
color: 0xdddddd,
shininess: 30,
specular: 0x222222
});
const cap = new THREE.Mesh(capGeometry, capMaterial);
cap.position.y = 0.85;
bottle.add(cap);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Animation
function animate() {
requestAnimationFrame(animate);
if (bottle) {
bottle.rotation.y += 0.005;
}
// Rotate particles slowly around Y axis
if (particleSystem) {
particleSystem.rotation.y += 0.001;
}
renderer.render(scene, camera);
}
// Initialisation des animations GSAP
function initAnimations() {
// Configuration des scènes
const scenes = document.querySelectorAll('.scene');
scenes.forEach((scene, index) => {
ScrollTrigger.create({
trigger: scene,
start: "top center",
end: "bottom center",
onEnter: () => {
scenes.forEach(s => s.classList.remove('active'));
scene.classList.add('active');
// Morph particles to current logo shape
const logoKey = `logo${index + 1}`;
if (logos[logoKey] && particleSystem) {
const positions = particleSystem.geometry.attributes.position.array;
const targetPositions = logos[logoKey];
// Animate each particle to its target position
for (let i = 0; i < particleCount; i++) {
const target = targetPositions[i];
gsap.to(positions, {
[i * 3]: target.x,
[i * 3 + 1]: target.y,
[i * 3 + 2]: target.z,
duration: 2,
ease: "power2.out",
onUpdate: () => {
particleSystem.geometry.attributes.position.needsUpdate = true;
}
});
}
}
// Animation spécifique à chaque scène
switch(index) {
case 0: // Apparition
gsap.to(bottle.material, { opacity: 1, duration: 1 });
gsap.to(camera.position, { z: 5, duration: 1 });
break;
case 1: // Rotation
gsap.to(bottle.rotation, { y: Math.PI * 2, duration: 5 });
break;
case 2: // Zoom avant
gsap.to(camera.position, { z: 2, duration: 1 });
break;
case 3: // Ouverture du bouchon
if (bottle.children.length > 0) {
gsap.to(bottle.children[0].position, { y: 1.2, duration: 0.5 });
}
break;
case 4: // Vue intérieure
gsap.to(bottle.material, { opacity: 0.5, duration: 0.5 });
break;
case 5: // Zoom arrière
gsap.to(camera.position, { z: 5, duration: 1 });
gsap.to(bottle.material, { opacity: 1, duration: 1 });
if (bottle.children.length > 0) {
gsap.to(bottle.children[0].position, { y: 0.85, duration: 0.5 });
}
break;
}
},
onEnterBack: () => {
scenes.forEach(s => s.classList.remove('active'));
scene.classList.add('active');
}
});
});
// Animation des cartes d'information
gsap.utils.toArray('.info-card').forEach((card, i) => {
ScrollTrigger.create({
trigger: card,
start: "top 80%",
onEnter: () => card.classList.add('visible'),
onLeaveBack: () => card.classList.remove('visible')
});
});
}
// Initialisation AOS
function initAOS() {
AOS.init({
duration: 800,
easing: 'ease-in-out',
once: false,
mirror: true
});
}
// Gestion du header
document.querySelector('.nav-toggle').addEventListener('click', function() {
this.classList.toggle('active');
document.querySelector('.main-nav').classList.toggle('active');
document.querySelector('.user-nav').classList.toggle('active');
});
// Initialisation au chargement
window.addEventListener('DOMContentLoaded', () => {
initThreeJS();
animate();
initAnimations();
initAOS();
// Animation d'apparition du header
setTimeout(() => {
document.querySelector('.nav-title').classList.add('visible');
document.querySelector('.nav-toggle').classList.add('visible');
}, 500);
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=sm08th/bootle" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>