All checks were successful
Deploy / Deploy to Production (push) Successful in 10s
La double extension .gltf.gltf suite au renommage du fichier source. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
446 lines
18 KiB
HTML
446 lines
18 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Moule à asperges — CERAMIQ+</title>
|
||
<link rel="stylesheet" href="style.css">
|
||
<script type="importmap">
|
||
{
|
||
"imports": {
|
||
"three": "https://cdn.jsdelivr.net/npm/three@0.169.0/build/three.module.js",
|
||
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.169.0/examples/jsm/"
|
||
}
|
||
}
|
||
</script>
|
||
<style>
|
||
.media-viewer::before { display: none; }
|
||
.media-viewer { background: var(--c-bg-subtle); }
|
||
.viewer-progress-track {
|
||
width: 160px;
|
||
height: 1px;
|
||
background: #ccc;
|
||
}
|
||
.viewer-progress-bar {
|
||
height: 100%;
|
||
width: 0%;
|
||
background: #111;
|
||
transition: width 0.12s linear;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<!-- ─── Header ──────────────────────────────────────── -->
|
||
<header class="site-header">
|
||
<a href="index.html" class="site-logo">CERAMIC+</a>
|
||
<nav class="header-nav">
|
||
<ul>
|
||
<li>Bibliothèque</li>
|
||
<li>Écosystème</li>
|
||
<li>Évènements</li>
|
||
</ul>
|
||
</nav>
|
||
<div class="header-actions">
|
||
<div class="search-wrap">
|
||
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/>
|
||
</svg>
|
||
<input type="text" placeholder="Rechercher une publication…">
|
||
</div>
|
||
<button class="btn-account btn-account--primary">
|
||
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>
|
||
</svg>
|
||
Se connecter
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
|
||
<nav class="obj-nav">
|
||
|
||
<a href="index.html" class="obj-back">
|
||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polyline points="15 18 9 12 15 6"/>
|
||
</svg>
|
||
Retour aux résultats
|
||
</a>
|
||
|
||
<div class="obj-nav-context">
|
||
<span class="obj-nav-path">
|
||
<a href="index.html">Moules</a>
|
||
<span class="bc-sep">›</span>
|
||
<a href="#">Céramique traditionnelle</a>
|
||
</span>
|
||
</div>
|
||
|
||
<div class="result-nav-filters">
|
||
<div class="filter">Argile</div>
|
||
<div class="filter">Espagne</div>
|
||
<div class="filter">Moulage</div>
|
||
</div>
|
||
|
||
<div class="obj-nav-arrows">
|
||
<button class="obj-arrow" title="Fiche précédente">
|
||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polyline points="15 18 9 12 15 6"/>
|
||
</svg>
|
||
</button>
|
||
<span class="obj-position">2 / 18</span>
|
||
<button class="obj-arrow" title="Fiche suivante">
|
||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polyline points="9 18 15 12 9 6"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
|
||
</nav>
|
||
|
||
<!-- ─── Contenu fiche objet ───────────────────────── -->
|
||
<div class="obj-wrap">
|
||
|
||
<!-- ─── En-tête ────────────────────────────────── -->
|
||
<header class="obj-header">
|
||
<div>
|
||
<h1 class="obj-title">Moule à asperges</h1>
|
||
<div class="card-meta" style="margin-top:10px">
|
||
<span class="meta-pill technique">Moulage</span>
|
||
<span class="meta-pill">Céramique traditionnelle</span>
|
||
<span class="meta-pill country">Espagne</span>
|
||
<span class="meta-pill">Argile</span>
|
||
<span class="meta-pill">XIXe siècle</span>
|
||
</div>
|
||
</div>
|
||
<div class="obj-header-actions">
|
||
<button class="btn-action">
|
||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
|
||
<polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>
|
||
</svg>
|
||
Télécharger
|
||
</button>
|
||
<button class="btn-action" onclick="window.print()">
|
||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polyline points="6 9 6 2 18 2 18 9"/>
|
||
<path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"/>
|
||
<rect x="6" y="14" width="12" height="8"/>
|
||
</svg>
|
||
Imprimer
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- ─── Corps : médias + info ────────────────────── -->
|
||
<div class="obj-body">
|
||
|
||
<!-- ─── Médias ──────────────────────────────────── -->
|
||
<section class="obj-media">
|
||
|
||
<div class="media-viewer">
|
||
<canvas id="viewer3d" style="position:absolute;inset:0;width:100%;height:100%;display:none;z-index:1;"></canvas>
|
||
<div class="media-viewer-inner" id="viewer-placeholder">
|
||
<div class="viewer-progress-track">
|
||
<div class="viewer-progress-bar" id="loader-bar"></div>
|
||
</div>
|
||
</div>
|
||
<div class="media-controls" style="z-index:3;">
|
||
<button class="ctrl-btn" title="Réinitialiser la vue">
|
||
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polyline points="1 4 1 10 7 10"/>
|
||
<path d="M3.51 15a9 9 0 1 0 .49-4.75"/>
|
||
</svg>
|
||
</button>
|
||
<button class="ctrl-btn" title="Zoom avant">
|
||
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>
|
||
<line x1="11" y1="8" x2="11" y2="14"/><line x1="8" y1="11" x2="14" y2="11"/>
|
||
</svg>
|
||
</button>
|
||
<button class="ctrl-btn" title="Zoom arrière">
|
||
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>
|
||
<line x1="8" y1="11" x2="14" y2="11"/>
|
||
</svg>
|
||
</button>
|
||
<button class="ctrl-btn ctrl-btn--sep" title="Plein écran">
|
||
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/>
|
||
<line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="media-thumbs">
|
||
<div class="thumb thumb--3d is-active">
|
||
<svg class="thumb-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#111" stroke-width="1.5">
|
||
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/>
|
||
<polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/>
|
||
</svg>
|
||
<span class="thumb-label">3D</span>
|
||
</div>
|
||
<div class="thumb">
|
||
<span class="thumb-label">IMG 1</span>
|
||
</div>
|
||
<div class="thumb">
|
||
<span class="thumb-label">IMG 2</span>
|
||
</div>
|
||
<div class="thumb thumb--portrait">
|
||
<span class="thumb-label">IMG 3</span>
|
||
</div>
|
||
<div class="thumb thumb--pdf">
|
||
<svg class="thumb-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#111" stroke-width="1.5">
|
||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
||
<polyline points="14 2 14 8 20 8"/>
|
||
<line x1="9" y1="13" x2="15" y2="13"/><line x1="9" y1="17" x2="15" y2="17"/>
|
||
</svg>
|
||
<span class="thumb-label">PDF</span>
|
||
</div>
|
||
</div>
|
||
|
||
</section>
|
||
|
||
<!-- ─── Panneau d'informations ─────────────────── -->
|
||
<aside class="obj-info">
|
||
|
||
<dl class="info-list">
|
||
|
||
<div class="info-row">
|
||
<dt>Pays / Région</dt>
|
||
<dd>Espagne<br><span class="info-sub">Castille-et-León</span></dd>
|
||
</div>
|
||
<hr class="info-divider">
|
||
<div class="info-row">
|
||
<dt>Partenaires</dt>
|
||
<dd>
|
||
Musée de la Céramique de Barcelone<br>
|
||
Universidad Complutense de Madrid<br>
|
||
<span class="info-sub">Réseau CERAMIQ, Partenaire associé</span>
|
||
</dd>
|
||
</div>
|
||
<hr class="info-divider">
|
||
<div class="info-row">
|
||
<dt>Auteur de la fiche</dt>
|
||
<dd>
|
||
Centre de Recherche Céramique Sud-Ouest<br>
|
||
</dd>
|
||
</div>
|
||
<hr class="info-divider">
|
||
<div class="info-row">
|
||
<dt>Date de publication</dt>
|
||
<dd>23 mars 2026<br><span class="info-sub">Mise à jour : 27 avril 2026</span></dd>
|
||
</div>
|
||
<hr class="info-divider">
|
||
<div class="info-row">
|
||
<dt>Lien vers la fiche sur le site du partenaire</dt>
|
||
<dd>23 mars 2026</dd>
|
||
</div>
|
||
</dl>
|
||
<button class="btn-contact-cta">
|
||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/>
|
||
<polyline points="22,6 12,13 2,6"/>
|
||
</svg>
|
||
Contacter l'auteur de la fiche
|
||
</button>
|
||
|
||
</aside>
|
||
|
||
</div>
|
||
|
||
<!-- ─── Description ────────────────────────────── -->
|
||
<section class="obj-section">
|
||
<h2 class="obj-section-title">Description</h2>
|
||
<div class="obj-description">
|
||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean congue ligula lorem, in cursus ligula condimentum eget. Fusce interdum nec sem quis euismod. Etiam turpis lorem, pharetra eu eros vel, ultricies dictum orci. Donec semper quam vitae nulla blandit, consectetur ultricies augue consequat. Maecenas fringilla efficitur metus, quis aliquet enim mattis sed. Morbi sed cursus ante. Vivamus rhoncus, mauris id posuere condimentum, augue nisi feugiat turpis, nec luctus sapien nisl vel ipsum.</p>
|
||
<p>Nullam auctor elit dictum, imperdiet magna eget, auctor sem. Pellentesque sodales, erat non varius tristique, massa quam scelerisque mi, et finibus purus diam ac turpis. Nam porta, leo ac iaculis blandit, dui augue tempor purus, nec fermentum arcu nulla sit amet erat.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ─── Pièces similaires ─────────────────────── -->
|
||
<section class="obj-section">
|
||
<h2 class="obj-section-title">Pièces similaires</h2>
|
||
<div class="obj-related-grid">
|
||
|
||
<article class="piece-card">
|
||
<div class="card-image"><span class="card-tag">Argile</span></div>
|
||
<div class="card-body">
|
||
<h2 class="card-name">Moule à tagine</h2>
|
||
<div class="card-meta">
|
||
<span class="meta-pill technique">Moulage</span>
|
||
<span class="meta-pill">Traditionnel</span>
|
||
<span class="meta-pill country">Espagne</span>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
|
||
<article class="piece-card">
|
||
<div class="card-image"><span class="card-tag">Kaolin</span></div>
|
||
<div class="card-body">
|
||
<h2 class="card-name">Moule à tarte</h2>
|
||
<div class="card-meta">
|
||
<span class="meta-pill technique">Coulage</span>
|
||
<span class="meta-pill">Traditionnel</span>
|
||
<span class="meta-pill country">Portugal</span>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
|
||
<article class="piece-card">
|
||
<div class="card-image"><span class="card-tag">Argile</span></div>
|
||
<div class="card-body">
|
||
<h2 class="card-name">Moule à brioche</h2>
|
||
<div class="card-meta">
|
||
<span class="meta-pill technique">Moulage</span>
|
||
<span class="meta-pill">Traditionnel</span>
|
||
<span class="meta-pill country">Occitanie</span>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
|
||
<article class="piece-card">
|
||
<div class="card-image"><span class="card-tag">Feldspath</span></div>
|
||
<div class="card-body">
|
||
<h2 class="card-name">Moule à charlotte</h2>
|
||
<div class="card-meta">
|
||
<span class="meta-pill technique">Coulage</span>
|
||
<span class="meta-pill">Traditionnel</span>
|
||
<span class="meta-pill country">Espagne</span>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
</div>
|
||
|
||
<script type="module">
|
||
import * as THREE from 'three';
|
||
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
||
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
||
|
||
const canvas = document.getElementById('viewer3d');
|
||
const pholder = document.getElementById('viewer-placeholder');
|
||
const viewer = document.querySelector('.media-viewer');
|
||
const bar = document.getElementById('loader-bar');
|
||
|
||
// ── Renderer ──────────────────────────────────────────
|
||
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true });
|
||
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
|
||
renderer.outputColorSpace = THREE.SRGBColorSpace;
|
||
renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
||
renderer.toneMappingExposure = 0.9;
|
||
|
||
// ── Scene / Camera ────────────────────────────────────
|
||
const scene = new THREE.Scene();
|
||
const camera = new THREE.PerspectiveCamera(40, 1, 0.001, 1000);
|
||
|
||
// ── Lights ────────────────────────────────────────────
|
||
scene.add(new THREE.AmbientLight(0xffffff, 1.5));
|
||
const key = new THREE.DirectionalLight(0xffffff, 2.5);
|
||
key.position.set(3, 5, 3);
|
||
scene.add(key);
|
||
const fill = new THREE.DirectionalLight(0xffffff, 0.6);
|
||
fill.position.set(-3, 2, -2);
|
||
scene.add(fill);
|
||
|
||
// ── Controls ──────────────────────────────────────────
|
||
const controls = new OrbitControls(camera, canvas);
|
||
controls.enableDamping = true;
|
||
controls.dampingFactor = 0.06;
|
||
|
||
// ── Model ─────────────────────────────────────────────
|
||
let initCamPos, initTarget;
|
||
|
||
new GLTFLoader().load(
|
||
'assets/3D-samples/moule%20asperges.gltf',
|
||
(gltf) => {
|
||
const model = gltf.scene;
|
||
const box = new THREE.Box3().setFromObject(model);
|
||
const c = box.getCenter(new THREE.Vector3());
|
||
const size = box.getSize(new THREE.Vector3());
|
||
const dim = Math.max(size.x, size.y, size.z);
|
||
|
||
model.position.sub(c);
|
||
scene.add(model);
|
||
|
||
camera.near = dim * 0.001;
|
||
camera.far = dim * 100;
|
||
camera.position.set(0, dim * 0.25, dim * 2.2);
|
||
controls.target.set(0, 0, 0);
|
||
controls.update();
|
||
|
||
initCamPos = camera.position.clone();
|
||
initTarget = controls.target.clone();
|
||
|
||
bar.style.width = '100%';
|
||
canvas.style.display = 'block';
|
||
pholder.style.display = 'none';
|
||
},
|
||
({ loaded, total }) => {
|
||
if (total) bar.style.width = `${Math.round(loaded / total * 100)}%`;
|
||
},
|
||
(err) => {
|
||
bar.style.background = '#c00';
|
||
console.error(err);
|
||
}
|
||
);
|
||
|
||
// ── Resize ────────────────────────────────────────────
|
||
function resize() {
|
||
const w = viewer.clientWidth, h = viewer.clientHeight;
|
||
camera.aspect = w / h;
|
||
camera.updateProjectionMatrix();
|
||
renderer.setSize(w, h);
|
||
}
|
||
resize();
|
||
new ResizeObserver(resize).observe(viewer);
|
||
|
||
// ── Render loop ───────────────────────────────────────
|
||
(function frame() {
|
||
requestAnimationFrame(frame);
|
||
controls.update();
|
||
renderer.render(scene, camera);
|
||
})();
|
||
|
||
// ── Boutons de contrôle ───────────────────────────────
|
||
document.querySelector('[title="Réinitialiser la vue"]')?.addEventListener('click', () => {
|
||
if (!initCamPos) return;
|
||
camera.position.copy(initCamPos);
|
||
controls.target.copy(initTarget);
|
||
controls.update();
|
||
});
|
||
|
||
document.querySelector('[title="Zoom avant"]')?.addEventListener('click', () => {
|
||
const d = camera.position.distanceTo(controls.target);
|
||
const dir = new THREE.Vector3().subVectors(controls.target, camera.position).normalize();
|
||
camera.position.addScaledVector(dir, d * 0.25);
|
||
controls.update();
|
||
});
|
||
|
||
document.querySelector('[title="Zoom arrière"]')?.addEventListener('click', () => {
|
||
const d = camera.position.distanceTo(controls.target);
|
||
const dir = new THREE.Vector3().subVectors(controls.target, camera.position).normalize();
|
||
camera.position.addScaledVector(dir, -d * 0.3);
|
||
controls.update();
|
||
});
|
||
|
||
document.querySelector('[title="Plein écran"]')?.addEventListener('click', () => {
|
||
document.fullscreenElement ? document.exitFullscreen() : viewer.requestFullscreen();
|
||
});
|
||
</script>
|
||
|
||
<!-- ─── Footer ──────────────────────────────────────── -->
|
||
<footer class="site-footer">
|
||
<span class="footer-logo">CERAMIQ+</span>
|
||
<div class="footer-links">
|
||
<a href="#">Mentions légales</a>
|
||
<a href="#">RGPD</a>
|
||
<a href="#">Contact</a>
|
||
</div>
|
||
</footer>
|
||
|
||
</body>
|
||
</html>
|