Files
le-shed_proto_formes/objets2.js
2026-05-18 23:07:31 +02:00

162 lines
7.5 KiB
JavaScript

/* ----------------------------------------------------------------
Le Shed — Objets v5-bach
Charge les SVGs de assets/shapes/v5-bach, les inline dans le DOM,
et répartit leurs formes unitaires entre deux layers (under/over)
pour que chaque objet traverse le contenu.
Horizontaux → côtés gauche et droit
Verticaux → centre (entre les colonnes)
Chaque objet a 5 formes unitaires (index 0..4).
Formes 0,1,2 → layer under (z-index:-1)
Formes 3,4 → layer over (z-index:20)
---------------------------------------------------------------- */
(function () {
/* ----------------------------------------------------------------
Catalogue de placement
side : 'left' | 'right' | 'center'
x : décalage depuis le bord (px, peut être négatif pour déborder)
y : position verticale depuis le haut du layout (px)
size : largeur cible en px (hauteur proportionnelle)
splitAt: index de la première forme qui passe en "over" (défaut: 3)
---------------------------------------------------------------- */
var CATALOGUE = [
// --- Horizontaux gauche ---
{ file: 'horizontaux/Group.svg', side: 'left', x: -100, y: 180, size: 255, speed: -1 },
{ file: 'horizontaux/Group-3.svg', side: 'left', x: -90, y: 550, size: 225, speed: 1.5 },
{ file: 'horizontaux/Group-6.svg', side: 'left', x: -110, y: 950, size: 270, speed: -1.5 },
{ file: 'horizontaux/Group-9.svg', side: 'left', x: -95, y: 1380, size: 240, speed: 1 },
{ file: 'horizontaux/Group-7.svg', side: 'left', x: -100, y: 1780, size: 245, speed: -1.5 },
// --- Horizontaux droite ---
{ file: 'horizontaux/Group-2.svg', side: 'right', x: -90, y: 350, size: 270, speed: 1.5 },
{ file: 'horizontaux/Group-5.svg', side: 'right', x: -105, y: 750, size: 245, speed: -1 },
{ file: 'horizontaux/Group-8.svg', side: 'right', x: -95, y: 1150, size: 255, speed: 1 },
{ file: 'horizontaux/Group-10.svg', side: 'right', x: -100, y: 1580, size: 285, speed: -1.5 },
{ file: 'horizontaux/Group-4.svg', side: 'right', x: -90, y: 1950, size: 240, speed: 1.5 },
// --- Verticaux centre ---
{ file: 'verticaux/Group.svg', side: 'center', x: -30, y: 280, size: 120, speed: 1 },
{ file: 'verticaux/Group-3.svg', side: 'center', x: 40, y: 650, size: 115, speed: -1.5 },
{ file: 'verticaux/Group-6.svg', side: 'center', x: -20, y: 1050, size: 125, speed: 1.5 },
{ file: 'verticaux/Group-9.svg', side: 'center', x: 35, y: 1450, size: 118, speed: -1 },
{ file: 'verticaux/Group-12.svg', side: 'center', x: -35, y: 1850, size: 120, speed: 1 },
{ file: 'verticaux/Group-4.svg', side: 'center', x: 25, y: 2200, size: 115, speed: -1.5 },
];
/* ----------------------------------------------------------------
Parse un SVG depuis le dictionnaire inline (pas de fetch)
---------------------------------------------------------------- */
function loadSVG(key) {
var data = window.LeShedObjets2Data;
if (!data || !data[key]) {
console.warn('LeShedObjets2: SVG non trouvé:', key);
return Promise.resolve(null);
}
var parser = new DOMParser();
var doc = parser.parseFromString(data[key], 'image/svg+xml');
var svgEl = doc.querySelector('svg');
if (!svgEl) return Promise.resolve(null);
var topG = svgEl.querySelector('svg > g');
if (!topG) return Promise.resolve(null);
var shapes = Array.from(topG.children).filter(function (c) {
return c.tagName === 'g';
});
return Promise.resolve({ svgEl: svgEl, shapes: shapes });
}
/* ----------------------------------------------------------------
Crée un <svg> clone avec les formes données, positionné en absolute
---------------------------------------------------------------- */
function makeSVGFragment(sourceSVG, shapes, spec, naturalW, naturalH) {
var targetW = spec.size;
var targetH = Math.round(naturalH * (targetW / naturalW));
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('viewBox', '0 0 ' + naturalW + ' ' + naturalH);
svg.setAttribute('width', targetW);
svg.setAttribute('height', targetH);
svg.setAttribute('fill', 'none');
if (spec.speed !== undefined) svg.setAttribute('data-rellax-speed', spec.speed);
svg.style.cssText = 'position:absolute;pointer-events:none;';
// Position horizontale
if (spec.side === 'left') {
svg.style.left = spec.x + 'px';
} else if (spec.side === 'right') {
svg.style.right = spec.x + 'px';
} else {
// center : centré entre les colonnes (centre de la page)
svg.style.left = '50%';
svg.style.marginLeft = (spec.x - targetW / 2) + 'px';
}
svg.style.top = spec.y + 'px';
// Copie les defs si présents
var defs = sourceSVG.querySelector('defs');
if (defs) svg.appendChild(defs.cloneNode(true));
shapes.forEach(function (g) {
svg.appendChild(g.cloneNode(true));
});
return svg;
}
/* ----------------------------------------------------------------
Inject principal
---------------------------------------------------------------- */
function injectObjets2() {
var layout = document.querySelector('.layout');
if (!layout) return Promise.resolve();
// Layer under : position absolute dans le layout, z-index négatif
var layerUnder = document.createElement('div');
layerUnder.className = 'objets2-layer objets2-layer--under';
layerUnder.style.cssText =
'position:absolute;inset:0;pointer-events:none;overflow:visible;z-index:-1';
// Layer over : position absolute dans le layout, z-index positif
var layerOver = document.createElement('div');
layerOver.className = 'objets2-layer objets2-layer--over';
layerOver.style.cssText =
'position:absolute;inset:0;pointer-events:none;overflow:visible;z-index:20';
// Insérer avant le contenu pour que le z-index fonctionne
layout.insertBefore(layerUnder, layout.firstChild);
layout.appendChild(layerOver);
var promises = CATALOGUE.map(function (spec) {
return loadSVG(spec.file).then(function (result) {
if (!result) return;
var shapes = result.shapes;
var svgEl = result.svgEl;
var naturalW = parseFloat(svgEl.getAttribute('width'));
var naturalH = parseFloat(svgEl.getAttribute('height'));
var splitAt = spec.splitAt !== undefined ? spec.splitAt : 3;
var shapesUnder = shapes.slice(0, splitAt);
var shapesOver = shapes.slice(splitAt);
if (shapesUnder.length) {
layerUnder.appendChild(
makeSVGFragment(svgEl, shapesUnder, spec, naturalW, naturalH)
);
}
if (shapesOver.length) {
layerOver.appendChild(
makeSVGFragment(svgEl, shapesOver, spec, naturalW, naturalH)
);
}
});
});
return Promise.all(promises);
}
window.LeShedObjets2 = { inject: injectObjets2 };
}());