first commit
This commit is contained in:
242
app.js
Normal file
242
app.js
Normal file
@@ -0,0 +1,242 @@
|
||||
/* ----------------------------------------------------------------
|
||||
Le Shed — Initialisation
|
||||
1. Injection des motifs décoratifs (formes vectorielles colorées)
|
||||
2. Initialisation de Rellax sur les objets décoratifs
|
||||
3. Parallax custom de la colonne droite :
|
||||
- Les deux colonnes démarrent à la même hauteur (top aligné)
|
||||
- Les deux colonnes finissent à la même hauteur (bottom aligné)
|
||||
- Le translateY est appliqué sur .col__cards (wrapper interne)
|
||||
pour ne pas casser le position:sticky du heading.
|
||||
---------------------------------------------------------------- */
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
/* ---- Header compact au scroll + padding-top dynamique ---- */
|
||||
|
||||
var masthead = document.querySelector('.masthead');
|
||||
var layout = document.querySelector('.layout');
|
||||
|
||||
var headerSyncing = false;
|
||||
|
||||
function syncHeaderHeight() {
|
||||
if (!masthead || !layout) return;
|
||||
var h = masthead.offsetHeight;
|
||||
layout.style.paddingTop = h + 'px';
|
||||
document.documentElement.style.setProperty('--header-h', h + 'px');
|
||||
}
|
||||
|
||||
function syncHeaderLoop() {
|
||||
syncHeaderHeight();
|
||||
syncColHeadingH();
|
||||
if (headerSyncing) requestAnimationFrame(syncHeaderLoop);
|
||||
}
|
||||
|
||||
function startHeaderSync() {
|
||||
if (headerSyncing) return;
|
||||
headerSyncing = true;
|
||||
syncHeaderLoop();
|
||||
setTimeout(function () {
|
||||
headerSyncing = false;
|
||||
syncHeaderHeight();
|
||||
}, 350);
|
||||
}
|
||||
|
||||
function syncColHeadingH() {
|
||||
var headingLeft = document.querySelector('.col--left .col__heading');
|
||||
if (headingLeft) {
|
||||
document.documentElement.style.setProperty('--col-heading-h', headingLeft.offsetHeight + 'px');
|
||||
}
|
||||
}
|
||||
|
||||
function onHeaderScroll() {
|
||||
if (!masthead) return;
|
||||
var scrolled = window.scrollY > 20;
|
||||
if (scrolled !== masthead.classList.contains('is-compact')) {
|
||||
masthead.classList.toggle('is-compact', scrolled);
|
||||
startHeaderSync();
|
||||
}
|
||||
}
|
||||
|
||||
syncHeaderHeight();
|
||||
syncColHeadingH();
|
||||
window.addEventListener('resize', function () { syncHeaderHeight(); syncColHeadingH(); });
|
||||
window.addEventListener('scroll', onHeaderScroll, { passive: true });
|
||||
onHeaderScroll();
|
||||
|
||||
/* ---- Rellax pour les objets décoratifs uniquement ---- */
|
||||
|
||||
function initRellax() {
|
||||
var rellax = new Rellax('[data-rellax-speed]', {
|
||||
center: false,
|
||||
wrapper: null,
|
||||
round: true,
|
||||
vertical: true,
|
||||
horizontal: false
|
||||
});
|
||||
|
||||
window.addEventListener('resize', function () {
|
||||
rellax.refresh();
|
||||
});
|
||||
}
|
||||
|
||||
/* ---- Parallax custom colonne droite ---- */
|
||||
|
||||
function initColumnParallax() {
|
||||
var colLeft = document.querySelector('.col--left');
|
||||
var colRight = document.querySelector('.col--right');
|
||||
var cardsRight = document.querySelector('.col--right .col__cards');
|
||||
if (!colLeft || !colRight || !cardsRight) return;
|
||||
|
||||
var titlesRight = Array.from(colRight.querySelectorAll('.col__cards .card__title'));
|
||||
var ticking = false;
|
||||
var dims = {};
|
||||
var maxScroll = 0;
|
||||
var currentOffset = 0;
|
||||
|
||||
// top de base des titres sticky (sans parallax)
|
||||
var baseStickyTop = 0;
|
||||
|
||||
function readBaseStickyTop() {
|
||||
var headerH = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--header-h')) || 80;
|
||||
var headingRight = colRight.querySelector('.col__heading');
|
||||
var colHeadingH = headingRight ? headingRight.offsetHeight : 35;
|
||||
baseStickyTop = headerH + colHeadingH - 2;
|
||||
}
|
||||
|
||||
function recalc() {
|
||||
cardsRight.style.transform = '';
|
||||
titlesRight.forEach(function (t) { t.style.top = ''; });
|
||||
layout.style.height = '';
|
||||
dims.leftH = colLeft.offsetHeight;
|
||||
dims.rightH = colRight.offsetHeight;
|
||||
|
||||
var cs = getComputedStyle(layout);
|
||||
var padTop = parseFloat(cs.paddingTop) || 0;
|
||||
var padBot = parseFloat(cs.paddingBottom) || 0;
|
||||
var minColH = Math.min(dims.leftH, dims.rightH);
|
||||
layout.style.height = (padTop + minColH + padBot) + 'px';
|
||||
|
||||
maxScroll = Math.max(1, document.documentElement.scrollHeight - window.innerHeight);
|
||||
readBaseStickyTop();
|
||||
}
|
||||
|
||||
function onScroll() {
|
||||
if (!ticking) {
|
||||
ticking = true;
|
||||
requestAnimationFrame(function () {
|
||||
readBaseStickyTop();
|
||||
var progress = Math.min(1, Math.max(0, window.scrollY / maxScroll));
|
||||
var delta = dims.leftH - dims.rightH;
|
||||
currentOffset = Math.round(delta * progress);
|
||||
cardsRight.style.transform = 'translateY(' + currentOffset + 'px)';
|
||||
// Compenser le translateY sur le top des titres sticky
|
||||
// pour qu'ils se collent toujours juste sous "Actions publiques"
|
||||
var correctedTop = baseStickyTop - currentOffset;
|
||||
titlesRight.forEach(function (t) {
|
||||
t.style.top = correctedTop + 'px';
|
||||
});
|
||||
ticking = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
recalc();
|
||||
window.addEventListener('scroll', onScroll, { passive: true });
|
||||
window.addEventListener('resize', function () {
|
||||
recalc();
|
||||
onScroll();
|
||||
});
|
||||
|
||||
onScroll();
|
||||
}
|
||||
|
||||
/* ---- Settings panel toggle ---- */
|
||||
|
||||
var settingsBtn = document.getElementById('settings-toggle');
|
||||
var settingsPanel = document.getElementById('settings-panel');
|
||||
|
||||
if (settingsBtn && settingsPanel) {
|
||||
settingsBtn.addEventListener('click', function () {
|
||||
settingsPanel.hidden = !settingsPanel.hidden;
|
||||
});
|
||||
|
||||
document.addEventListener('click', function (e) {
|
||||
if (!document.getElementById('settings').contains(e.target)) {
|
||||
settingsPanel.hidden = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* ---- Switch motifs ---- */
|
||||
|
||||
var rellaxInstance = null;
|
||||
|
||||
function clearMotifs() {
|
||||
document.querySelectorAll('.objets-layer, .objets2-layer, .paysage-layer').forEach(function (el) {
|
||||
el.remove();
|
||||
});
|
||||
if (rellaxInstance) {
|
||||
try { rellaxInstance.destroy(); } catch (e) {}
|
||||
rellaxInstance = null;
|
||||
}
|
||||
}
|
||||
|
||||
function activateMotif(mode) {
|
||||
clearMotifs();
|
||||
if (mode === 'paysage' && window.LeShedPaysage) {
|
||||
window.LeShedPaysage.inject().then(function () {
|
||||
rellaxInstance = new Rellax('[data-rellax-speed]', { center: false, round: true, vertical: true, horizontal: false });
|
||||
});
|
||||
} else if (mode === 'objets' && window.LeShedObjets) {
|
||||
window.LeShedObjets.inject().then(function () {
|
||||
rellaxInstance = new Rellax('[data-rellax-speed]', { center: false, round: true, vertical: true, horizontal: false });
|
||||
});
|
||||
} else if (mode === 'objets2' && window.LeShedObjets2) {
|
||||
window.LeShedObjets2.inject().then(function () {
|
||||
rellaxInstance = new Rellax('[data-rellax-speed]', { center: false, round: true, vertical: true, horizontal: false });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelectorAll('input[name="motifs"]').forEach(function (radio) {
|
||||
radio.addEventListener('change', function () {
|
||||
if (radio.checked) activateMotif(radio.value);
|
||||
});
|
||||
});
|
||||
|
||||
/* ---- Couleur motifs ---- */
|
||||
|
||||
var couleurCustomInput = document.getElementById('couleur-custom');
|
||||
|
||||
function applyMotifColor(value) {
|
||||
var color = value === 'custom' ? couleurCustomInput.value : value;
|
||||
document.documentElement.style.setProperty('--motif-color', color);
|
||||
}
|
||||
|
||||
document.querySelectorAll('input[name="couleur"]').forEach(function (radio) {
|
||||
radio.addEventListener('change', function () {
|
||||
if (radio.checked) applyMotifColor(radio.value);
|
||||
});
|
||||
});
|
||||
|
||||
if (couleurCustomInput) {
|
||||
couleurCustomInput.addEventListener('input', function () {
|
||||
var customRadio = document.querySelector('input[name="couleur"][value="custom"]');
|
||||
if (customRadio) customRadio.checked = true;
|
||||
applyMotifColor('custom');
|
||||
});
|
||||
}
|
||||
|
||||
/* ---- Boot ---- */
|
||||
|
||||
document.querySelectorAll('input[name="motifs"]').forEach(function (r) {
|
||||
r.checked = r.value === 'objets2';
|
||||
});
|
||||
document.querySelectorAll('input[name="couleur"]').forEach(function (r) {
|
||||
r.checked = r.value === '#1a1a1a';
|
||||
});
|
||||
applyMotifColor('#1a1a1a');
|
||||
activateMotif('objets2');
|
||||
initColumnParallax();
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user