Bootstrap
Bootstrap5
Dashboard
Admin
Widgets
Html
Template Bootstrap 5 de page produits 360 avec différents widgets et graphiques.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="copyright" content="MEZGANI Said" />
<meta name="author" content="AngularForAll" />
<meta name="robots" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Product Detail 360 Bootstrap 5 02 | AngularForAll</title>
<!-- Bootstrap 5 + Icons -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<!-- Lightbox pour galerie photos -->
<link href="https://cdn.jsdelivr.net/npm/lightbox2@2.11.4/dist/css/lightbox.min.css" rel="stylesheet">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Inter', sans-serif;
background: linear-gradient(135deg, #f5f7fc 0%, #eef1f7 100%);
color: #1e293b;
}
/* Header */
.navbar-product {
background: rgba(255,255,255,0.9);
backdrop-filter: blur(10px);
box-shadow: 0 4px 20px rgba(0,0,0,0.03);
padding: 1rem 2rem;
border-bottom: 1px solid rgba(0,0,0,0.05);
position: sticky;
top: 0;
z-index: 100;
}
.breadcrumb {
margin: 0;
font-size: 0.9rem;
}
.breadcrumb a {
color: #64748b;
text-decoration: none;
}
/* Layout */
.product-container {
max-width: 1400px;
margin: 2rem auto;
padding: 0 1.5rem;
}
/* Section Viewer (3D + Photos) */
.viewer-section {
background: white;
border-radius: 32px;
padding: 24px;
box-shadow: 0 20px 40px -12px rgba(0,0,0,0.1);
margin-bottom: 30px;
}
/* Tabs 3D / Photos */
.viewer-tabs {
display: flex;
gap: 12px;
margin-bottom: 20px;
border-bottom: 2px solid #eef2f6;
padding-bottom: 12px;
}
.viewer-tab {
padding: 10px 24px;
border-radius: 30px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
color: #64748b;
background: transparent;
border: none;
}
.viewer-tab.active {
background: #0f172a;
color: white;
}
.viewer-tab i {
margin-right: 8px;
}
/* Conteneur 3D */
#viewer-3d-container {
display: block;
position: relative;
}
#viewer-3d-container.hidden {
display: none;
}
#canvas-wrapper {
width: 100%;
aspect-ratio: 1 / 1;
border-radius: 24px;
overflow: hidden;
background: linear-gradient(145deg, #0f172a, #1e293b);
box-shadow: inset 0 0 30px #00000040, 0 10px 30px rgba(0,0,0,0.2);
}
canvas {
display: block;
width: 100%;
height: 100%;
outline: none;
}
.viewer-badge {
position: absolute;
bottom: 20px;
left: 20px;
background: rgba(20,30,50,0.8);
backdrop-filter: blur(12px);
color: white;
padding: 6px 18px;
border-radius: 40px;
font-size: 0.8rem;
border: 1px solid rgba(255,255,255,0.2);
z-index: 5;
}
.rotate-hint {
position: absolute;
bottom: 20px;
right: 20px;
background: rgba(0,0,0,0.5);
backdrop-filter: blur(8px);
color: #ccd6f6;
padding: 6px 16px;
border-radius: 30px;
font-size: 0.8rem;
z-index: 5;
}
/* Conteneur Photos */
#photos-container {
display: none;
}
#photos-container.active {
display: block;
}
.photo-gallery {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
gap: 16px;
}
.gallery-main {
grid-row: span 2;
border-radius: 20px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
}
.gallery-main img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s;
}
.gallery-main img:hover {
transform: scale(1.02);
}
.gallery-thumb {
border-radius: 20px;
overflow: hidden;
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
cursor: pointer;
}
.gallery-thumb img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s;
}
.gallery-thumb img:hover {
transform: scale(1.05);
}
/* Infos produit */
.product-title {
font-size: 2.5rem;
font-weight: 700;
letter-spacing: -0.02em;
margin-bottom: 0.5rem;
}
.product-ref {
color: #64748b;
font-size: 0.9rem;
margin-bottom: 1rem;
}
.price-section {
display: flex;
align-items: baseline;
gap: 15px;
margin: 20px 0;
}
.current-price {
font-size: 2.5rem;
font-weight: 700;
color: #0f172a;
}
.old-price {
font-size: 1.3rem;
color: #94a3b8;
text-decoration: line-through;
}
.discount-badge {
background: #ef4444;
color: white;
padding: 4px 12px;
border-radius: 30px;
font-weight: 600;
font-size: 0.9rem;
}
.stock-status {
display: inline-flex;
align-items: center;
background: #dcfce7;
color: #15803d;
padding: 6px 16px;
border-radius: 30px;
font-weight: 500;
margin-bottom: 20px;
}
/* Sélecteurs */
.selector-section {
margin: 25px 0;
}
.selector-title {
font-weight: 600;
margin-bottom: 12px;
color: #334155;
}
.color-options {
display: flex;
gap: 16px;
flex-wrap: wrap;
}
.color-option {
cursor: pointer;
text-align: center;
transition: all 0.2s;
}
.color-dot {
width: 48px;
height: 48px;
border-radius: 48px;
border: 3px solid transparent;
box-shadow: 0 4px 10px rgba(0,0,0,0.1);
margin-bottom: 6px;
}
.color-option.active .color-dot {
border-color: #0f172a;
transform: scale(1.1);
}
.color-option span {
font-size: 0.85rem;
font-weight: 500;
}
.storage-options {
display: flex;
gap: 12px;
}
.storage-btn {
padding: 12px 24px;
border: 2px solid #e2e8f0;
border-radius: 16px;
background: white;
font-weight: 600;
transition: all 0.2s;
cursor: pointer;
}
.storage-btn.active {
border-color: #0f172a;
background: #0f172a;
color: white;
}
.storage-btn:hover {
border-color: #0f172a;
}
/* Boutons action */
.action-buttons {
display: flex;
gap: 16px;
margin: 30px 0;
}
.btn-add-cart {
flex: 1;
background: #0f172a;
color: white;
border: none;
padding: 18px 32px;
border-radius: 60px;
font-weight: 600;
font-size: 1.1rem;
transition: all 0.2s;
box-shadow: 0 10px 25px -5px rgba(15,23,42,0.3);
}
.btn-add-cart:hover {
background: #1e293b;
transform: translateY(-2px);
box-shadow: 0 15px 30px -5px rgba(15,23,42,0.4);
}
.btn-like {
width: 60px;
background: white;
border: 2px solid #e2e8f0;
border-radius: 60px;
font-size: 1.5rem;
color: #ef4444;
transition: all 0.2s;
cursor: pointer;
}
.btn-like:hover {
background: #fef2f2;
border-color: #fca5a5;
}
.btn-like.liked {
background: #ef4444;
color: white;
border-color: #ef4444;
}
.btn-like.liked i {
color: white;
}
/* Description */
.description-box {
background: white;
border-radius: 24px;
padding: 28px;
margin-top: 24px;
box-shadow: 0 8px 24px rgba(0,0,0,0.04);
}
.specs-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 20px;
margin-top: 20px;
}
.spec-item {
text-align: center;
padding: 16px;
background: #f8fafc;
border-radius: 16px;
}
.spec-item i {
font-size: 2rem;
color: #0f172a;
margin-bottom: 10px;
}
/* Responsive */
@media (max-width: 992px) {
.product-container { padding: 0 1rem; }
.product-title { font-size: 2rem; }
.photo-gallery { grid-template-columns: 1fr 1fr; }
.gallery-main { grid-column: span 2; }
}
@media (max-width: 768px) {
.photo-gallery { grid-template-columns: 1fr; }
.gallery-main { grid-column: span 1; }
.action-buttons { flex-direction: column; }
.btn-like { width: 100%; }
}
</style>
<!-- Three.js -->
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.128.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.128.0/examples/jsm/"
}
}
</script>
</head>
<body>
<!-- Navigation -->
<nav class="navbar-product d-flex align-items-center justify-content-between">
<div class="d-flex align-items-center gap-3">
<i class="bi bi-shop fs-3" style="color: #0f172a;"></i>
<span style="font-weight: 700; font-size: 1.3rem;">TechStore</span>
</div>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="#">Accueil</a></li>
<li class="breadcrumb-item"><a href="#">Smartphones</a></li>
<li class="breadcrumb-item active">Smartphone X10</li>
</ol>
</nav>
</nav>
<!-- Contenu principal -->
<div class="product-container">
<div class="row g-4">
<!-- Colonne gauche : Visualiseur (3D + Photos) -->
<div class="col-lg-7">
<div class="viewer-section">
<!-- Tabs -->
<div class="viewer-tabs">
<button class="viewer-tab active" onclick="switchViewer('3d')">
<i class="bi bi-badge-3d"></i> Vue 3D 360°
</button>
<button class="viewer-tab" onclick="switchViewer('photos')">
<i class="bi bi-images"></i> Photos
</button>
</div>
<!-- Viewer 3D -->
<div id="viewer-3d-container">
<div id="canvas-wrapper">
<canvas id="phone-canvas"></canvas>
</div>
<div class="viewer-badge">
<i class="bi bi-arrow-repeat me-1"></i> Faites glisser pour tourner à 360°
</div>
<div class="rotate-hint">
<i class="bi bi-mouse me-1"></i> Zoom avec la molette
</div>
</div>
<!-- Viewer Photos -->
<div id="photos-container">
<div class="photo-gallery">
<!-- Photo principale -->
<div class="gallery-main">
<a href="public/mobile.png" data-lightbox="product-gallery" data-title="Smartphone X10 - Vue face">
<img src="public/mobile.png" alt="Smartphone face">
</a>
</div>
<!-- Photos secondaires -->
<div class="gallery-thumb">
<a href="public/mobile.png" data-lightbox="product-gallery" data-title="Smartphone X10 - Vue arrière">
<img src="public/mobile.png" alt="Vue arrière">
</a>
</div>
<div class="gallery-thumb">
<a href="public/mobile.png" data-lightbox="product-gallery" data-title="Smartphone X10 - Vue côté">
<img src="public/mobile.png" alt="Vue côté">
</a>
</div>
<div class="gallery-thumb">
<a href="public/mobile.png" data-lightbox="product-gallery" data-title="Smartphone X10 - Détail caméra">
<img src="public/mobile.png" alt="Détail caméra">
</a>
</div>
<div class="gallery-thumb">
<a href="public/mobile.png" data-lightbox="product-gallery" data-title="Smartphone X10 - Accessoires">
<img src="public/mobile.png" alt="Accessoires">
</a>
</div>
</div>
<!-- Note : Remplacez les URLs ci-dessus par vos propres photos -->
<div class="alert alert-info mt-3 mb-0">
<i class="bi bi-info-circle me-2"></i>
<strong>Personnalisation :</strong> Remplacez les URLs des images dans le code par vos propres photos (ex: https://votresite.com/photo.jpg)
</div>
</div>
<!-- Miniatures couleurs rapide -->
<div class="d-flex gap-3 mt-3 justify-content-center">
<div class="color-option active" onclick="setPhoneColor(0x2c2c36, this)">
<div class="color-dot" style="background: #2c2c36;"></div>
<span>Noir</span>
</div>
<div class="color-option" onclick="setPhoneColor(0xc0b7a8, this)">
<div class="color-dot" style="background: #c0b7a8;"></div>
<span>Argent</span>
</div>
<div class="color-option" onclick="setPhoneColor(0x4a6fa5, this)">
<div class="color-dot" style="background: #4a6fa5;"></div>
<span>Bleu</span>
</div>
</div>
</div>
</div>
<!-- Colonne droite : Infos produit -->
<div class="col-lg-5">
<div class="ps-lg-3">
<!-- Titre et référence -->
<h1 class="product-title">Smartphone X10 5G</h1>
<div class="product-ref">
<i class="bi bi-upc-scan me-1"></i> Réf: SM-X10-256-BK ·
<span class="text-warning ms-2">
<i class="bi bi-star-fill"></i> 4.7 (156 avis)
</span>
</div>
<!-- Prix -->
<div class="price-section">
<span class="current-price">749 €</span>
<span class="old-price">899 €</span>
<span class="discount-badge">-17%</span>
</div>
<!-- Stock -->
<div class="stock-status">
<i class="bi bi-check-circle-fill me-2"></i>
En stock · Livraison 24-48h
</div>
<!-- Sélecteur Couleur -->
<div class="selector-section">
<div class="selector-title">
<i class="bi bi-palette me-2"></i>Couleur
</div>
<div class="color-options">
<div class="color-option active" onclick="setPhoneColor(0x2c2c36, this); updateMainPhoto('noir')">
<div class="color-dot" style="background: #2c2c36;"></div>
<span>Noir Graphite</span>
</div>
<div class="color-option" onclick="setPhoneColor(0xc0b7a8, this); updateMainPhoto('argent')">
<div class="color-dot" style="background: #c0b7a8;"></div>
<span>Argent Titane</span>
</div>
<div class="color-option" onclick="setPhoneColor(0x4a6fa5, this); updateMainPhoto('bleu')">
<div class="color-dot" style="background: #4a6fa5;"></div>
<span>Bleu Océan</span>
</div>
</div>
</div>
<!-- Sélecteur Stockage -->
<div class="selector-section">
<div class="selector-title">
<i class="bi bi-memory me-2"></i>Stockage
</div>
<div class="storage-options">
<div class="storage-btn active" onclick="selectStorage(this, 749)">128 Go</div>
<div class="storage-btn" onclick="selectStorage(this, 869)">256 Go</div>
<div class="storage-btn" onclick="selectStorage(this, 1029)">512 Go</div>
</div>
</div>
<!-- Boutons d'action -->
<div class="action-buttons">
<button class="btn-add-cart" onclick="addToCart()">
<i class="bi bi-cart-plus me-2"></i>Ajouter au panier
</button>
<button class="btn-like" id="likeButton" onclick="toggleLike()" aria-label="Ajouter aux favoris">
<i class="bi bi-heart"></i>
</button>
</div>
<!-- Livraison / Garantie -->
<div class="d-flex gap-3 text-secondary small mb-4">
<span><i class="bi bi-truck me-1"></i> Livraison offerte</span>
<span><i class="bi bi-shield-check me-1"></i> Garantie 2 ans</span>
<span><i class="bi bi-arrow-return-left me-1"></i> Retour gratuit</span>
</div>
<!-- Description -->
<div class="description-box">
<h5 class="fw-bold mb-3">
<i class="bi bi-file-text me-2"></i>Description
</h5>
<p>Le Smartphone X10 5G offre une expérience fluide avec son processeur octa-core, son écran AMOLED 6.7" 120Hz et sa batterie 5000 mAh. Capturez des photos exceptionnelles avec le triple capteur 108MP et profitez de la charge rapide 67W.</p>
<div class="specs-grid">
<div class="spec-item">
<i class="bi bi-cpu"></i>
<div class="fw-bold">Snapdragon 8</div>
<small>Gen 3</small>
</div>
<div class="spec-item">
<i class="bi bi-battery-charging"></i>
<div class="fw-bold">5000 mAh</div>
<small>Charge 67W</small>
</div>
<div class="spec-item">
<i class="bi bi-camera"></i>
<div class="fw-bold">108 MP</div>
<small>Triple caméra</small>
</div>
<div class="spec-item">
<i class="bi bi-droplet-half"></i>
<div class="fw-bold">IP68</div>
<small>Étanche</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Scripts -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lightbox2@2.11.4/dist/js/lightbox.min.js"></script>
<script type="module">
// --- THREE.JS : Visualisation 3D 360° ---
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
let scene, camera, renderer, controls, phoneBodyMaterial, phoneGroup;
const canvas = document.getElementById('phone-canvas');
function initThree() {
scene = new THREE.Scene();
scene.background = new THREE.Color('#0f172a');
camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
camera.position.set(3, 2, 5);
renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
renderer.setSize(canvas.clientWidth, canvas.clientHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.autoRotate = true;
controls.autoRotateSpeed = 1.8;
controls.enableZoom = true;
controls.enablePan = false;
controls.target.set(0, 0.5, 0);
controls.maxPolarAngle = Math.PI / 1.8;
controls.minDistance = 2.2;
controls.maxDistance = 7.0;
// Lumières
scene.add(new THREE.AmbientLight(0x404060, 0.55));
const mainLight = new THREE.DirectionalLight(0xfff5e6, 1.2);
mainLight.position.set(4, 6, 3);
mainLight.castShadow = true;
mainLight.receiveShadow = true;
mainLight.shadow.mapSize.width = 1024;
mainLight.shadow.mapSize.height = 1024;
scene.add(mainLight);
const fill1 = new THREE.PointLight(0x4466cc, 0.7);
fill1.position.set(-3, 2, 4);
scene.add(fill1);
const fill2 = new THREE.PointLight(0xccaa88, 0.5);
fill2.position.set(2, 1, -5);
scene.add(fill2);
const backLight = new THREE.PointLight(0x6688aa, 0.4);
backLight.position.set(-1, 1.5, -6);
scene.add(backLight);
// Sol
const planeGeo = new THREE.CircleGeometry(4, 20);
const planeMat = new THREE.MeshStandardMaterial({ color: 0x1a2332, roughness: 0.4, metalness: 0.1, side: THREE.DoubleSide });
const plane = new THREE.Mesh(planeGeo, planeMat);
plane.rotation.x = -Math.PI/2;
plane.position.y = -0.01;
plane.receiveShadow = true;
scene.add(plane);
// Grille
const grid = new THREE.GridHelper(6, 20, 0x88aaff, 0x334466);
grid.position.y = 0;
scene.add(grid);
// Construction du téléphone
phoneGroup = new THREE.Group();
const bodyMat = new THREE.MeshStandardMaterial({ color: 0x2c2c36, roughness: 0.25, metalness: 0.4 });
phoneBodyMaterial = bodyMat;
const mainBody = new THREE.Mesh(new THREE.BoxGeometry(1.6, 3.2, 0.32), bodyMat);
mainBody.castShadow = true;
mainBody.receiveShadow = true;
mainBody.position.y = 0.5;
phoneGroup.add(mainBody);
// Écran
const screenMat = new THREE.MeshStandardMaterial({
color: 0x0a0e14,
roughness: 0.15,
emissive: new THREE.Color(0x112233),
emissiveIntensity: 0.3
});
const screen = new THREE.Mesh(new THREE.BoxGeometry(1.45, 2.95, 0.05), screenMat);
screen.castShadow = true;
screen.position.set(0, 0.5, 0.165);
phoneGroup.add(screen);
// Cadre
const frameMat = new THREE.MeshStandardMaterial({ color: 0xccccdd, roughness: 0.2, metalness: 0.8 });
const frontFrame = new THREE.Mesh(new THREE.BoxGeometry(1.58, 3.18, 0.02), frameMat);
frontFrame.position.set(0, 0.5, 0.19);
phoneGroup.add(frontFrame);
// Module caméra
const camMod = new THREE.Mesh(new THREE.CylinderGeometry(0.25, 0.25, 0.04), new THREE.MeshStandardMaterial({ color: 0x333338 }));
camMod.rotation.y = 0.3;
camMod.position.set(0.3, 1.35, -0.18);
phoneGroup.add(camMod);
// Lentilles
const lens1 = new THREE.Mesh(new THREE.CylinderGeometry(0.1, 0.1, 0.03), new THREE.MeshStandardMaterial({ color: 0x111116 }));
lens1.rotation.x = Math.PI/2;
lens1.position.set(0.3, 1.35, -0.2);
phoneGroup.add(lens1);
scene.add(phoneGroup);
// Animation
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
// Redimensionnement
const resizeObserver = new ResizeObserver(() => {
const wrapper = document.getElementById('canvas-wrapper');
const w = wrapper.clientWidth;
renderer.setSize(w, w);
camera.aspect = 1;
camera.updateProjectionMatrix();
});
resizeObserver.observe(document.getElementById('canvas-wrapper'));
}
initThree();
// Fonction globale pour changer couleur 3D
window.setPhoneColor = (hexColor, element) => {
if (phoneBodyMaterial) {
phoneBodyMaterial.color.setHex(hexColor);
}
// Mise à jour UI
if (element) {
document.querySelectorAll('.color-option').forEach(opt => opt.classList.remove('active'));
element.classList.add('active');
}
};
// Désactiver auto-rotate après interaction
canvas.addEventListener('mousedown', () => controls.autoRotate = false);
canvas.addEventListener('touchstart', () => controls.autoRotate = false);
let idleTimer;
window.addEventListener('mousemove', () => {
controls.autoRotate = false;
clearTimeout(idleTimer);
idleTimer = setTimeout(() => controls.autoRotate = true, 4000);
});
</script>
<script>
// --- Fonctions UI ---
// Switch entre 3D et Photos
window.switchViewer = (mode) => {
const container3D = document.getElementById('viewer-3d-container');
const containerPhotos = document.getElementById('photos-container');
const tabs = document.querySelectorAll('.viewer-tab');
tabs.forEach(tab => tab.classList.remove('active'));
if (mode === '3d') {
container3D.classList.remove('hidden');
containerPhotos.classList.remove('active');
tabs[0].classList.add('active');
// Redimensionner canvas
setTimeout(() => {
const wrapper = document.getElementById('canvas-wrapper');
const w = wrapper.clientWidth;
const canvas = document.getElementById('phone-canvas');
const renderer = canvas.getContext('webgl2') || canvas.getContext('webgl');
if (renderer) {
canvas.style.width = w + 'px';
canvas.style.height = w + 'px';
}
}, 50);
} else {
container3D.classList.add('hidden');
containerPhotos.classList.add('active');
tabs[1].classList.add('active');
// Réinitialiser lightbox
if (typeof lightbox !== 'undefined') {
lightbox.option({
'resizeDuration': 200,
'wrapAround': true,
'albumLabel': 'Image %1 sur %2'
});
}
}
};
// Sélection stockage
window.selectStorage = (element, price) => {
document.querySelectorAll('.storage-btn').forEach(btn => btn.classList.remove('active'));
element.classList.add('active');
document.querySelector('.current-price').textContent = price + ' €';
};
// Ajouter au panier
window.addToCart = () => {
const color = document.querySelector('.color-option.active span')?.textContent || 'Noir';
const storage = document.querySelector('.storage-btn.active')?.textContent || '128 Go';
const price = document.querySelector('.current-price').textContent;
alert(`✅ Ajouté au panier !\n\nSmartphone X10\nCouleur: ${color}\nStockage: ${storage}\nPrix: ${price}`);
};
// Like
window.toggleLike = () => {
const btn = document.getElementById('likeButton');
const icon = btn.querySelector('i');
btn.classList.toggle('liked');
if (btn.classList.contains('liked')) {
icon.classList.remove('bi-heart');
icon.classList.add('bi-heart-fill');
} else {
icon.classList.remove('bi-heart-fill');
icon.classList.add('bi-heart');
}
};
// Mise à jour photo principale (simulation)
window.updateMainPhoto = (color) => {
// Cette fonction peut être étendue pour changer les photos selon la couleur
console.log('Couleur sélectionnée :', color);
// Exemple: changer l'image principale selon la couleur
// document.querySelector('.gallery-main img').src = `https://votresite.com/phone-${color}.jpg`;
};
// Initialisation lightbox
document.addEventListener('DOMContentLoaded', () => {
if (typeof lightbox !== 'undefined') {
lightbox.option({
'resizeDuration': 200,
'wrapAround': true,
'albumLabel': 'Image %1 sur %2',
'fadeDuration': 300
});
}
});
</script>
<!-- Note d'utilisation -->
<div style="position: fixed; bottom: 20px; left: 20px; background: rgba(255,255,255,0.9); padding: 8px 16px; border-radius: 30px; font-size: 0.8rem; box-shadow: 0 4px 12px rgba(0,0,0,0.1); z-index: 1000;">
<i class="bi bi-image me-1"></i>
<strong>Personnalisez :</strong> Remplacez les URLs des photos dans le code HTML (lignes avec picsum.photos)
</div>
</body>
</html>
Ouvrir cet aperçu dans un nouvel onglet du navigateur
🔗 Ouvrir dans le navigateur