décors mid-left au pied des colonnes avec parallax custom
This commit is contained in:
@@ -954,6 +954,15 @@ main.main-login .login > div > div:not(.hidden) form .button:hover, main.main-lo
|
|||||||
height: 22vh;
|
height: 22vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.col-decor {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
@media (min-width: 760px) {
|
||||||
|
.col-decor {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* PAGES */
|
/* PAGES */
|
||||||
.home_introduction {
|
.home_introduction {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|||||||
@@ -391,13 +391,19 @@
|
|||||||
|
|
||||||
const asideProjectMenu = document.querySelector('#block-erabletheme-views-block-projets-block-1 .projets_list');
|
const asideProjectMenu = document.querySelector('#block-erabletheme-views-block-projets-block-1 .projets_list');
|
||||||
if (asideProjectMenu) {
|
if (asideProjectMenu) {
|
||||||
|
// Le titre du projet n'est plus rendu dans .projet_full depuis la
|
||||||
|
// refonte (il a été remonté dans .page-header-outside, hors colonne
|
||||||
|
// blanche). On va chercher le titre courant à sa nouvelle place.
|
||||||
|
// Garde sur null + chaîne vide pour éviter l'exception qui plantait
|
||||||
|
// tout le behavior attach (et donc Rellax) sur /projets/<slug>.
|
||||||
|
const headerOutside = document.querySelector('.layout-content .page-header-outside h2');
|
||||||
|
const contentPageTitle = (headerOutside?.innerText || '').trim().toLowerCase();
|
||||||
|
if (contentPageTitle) {
|
||||||
for (let item of asideProjectMenu.children) {
|
for (let item of asideProjectMenu.children) {
|
||||||
const itemTitle = item.innerText;
|
const itemTitle = (item.innerText || '').trim().toLowerCase();
|
||||||
const contentPage = document.querySelector('.projet_full');
|
if (itemTitle === contentPageTitle) {
|
||||||
const contentPageTitle = contentPage.querySelector('h2')?.innerText;
|
item.querySelector('a')?.classList.add('is-active');
|
||||||
|
}
|
||||||
if (itemTitle.toLowerCase() === contentPageTitle.toLowerCase()) {
|
|
||||||
item.querySelector('a').classList.add('is-active');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -433,6 +439,133 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Décors mid-left : 0, 1 ou 2 PNG empilés au pied gauche extérieur
|
||||||
|
// de chaque .fullpage interne (pages non-index). Tailles et gaps
|
||||||
|
// proportionnels à colH, bornés min/max. On n'affiche un motif
|
||||||
|
// que si la pile tient sous 50% colH (les deux) ou 30% (un seul),
|
||||||
|
// sinon la forme déborderait dans le contenu en haut.
|
||||||
|
// Position absolue calculée en px dans .layout-container ;
|
||||||
|
// bord droit du PNG calé sur bord gauche colonne via
|
||||||
|
// translateX(-100%). Parallax custom plus bas (sans Rellax).
|
||||||
|
// Visibilité responsive : _background.scss.
|
||||||
|
//
|
||||||
|
const layoutContainer = document.querySelector('.layout-container');
|
||||||
|
const colDecorState = []; // { img1, img2, col }
|
||||||
|
|
||||||
|
function clamp(min, val, max) { return Math.max(min, Math.min(val, max)); }
|
||||||
|
|
||||||
|
function colDecorMetrics(colH) {
|
||||||
|
return {
|
||||||
|
gapBottom: clamp(120, 0.08 * colH, 320),
|
||||||
|
gapBetween: clamp(60, 0.03 * colH, 180),
|
||||||
|
h2: clamp(180, 0.14 * colH, 480),
|
||||||
|
h1: clamp(220, 0.17 * colH, 580),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createColDecorImg(idx) {
|
||||||
|
const img = document.createElement('img');
|
||||||
|
img.className = `col-decor col-decor-${idx}`;
|
||||||
|
img.setAttribute('aria-hidden', 'true');
|
||||||
|
img.setAttribute('alt', '');
|
||||||
|
img.src = `/themes/erabletheme/assets/new-bg-shapes/mid-left-${idx}.png`;
|
||||||
|
img.style.cssText = 'position:absolute;width:auto;pointer-events:none;z-index:0;transform:translateX(-100%);';
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupColDecor() {
|
||||||
|
if (!layoutContainer) return;
|
||||||
|
layoutContainer.querySelectorAll('.col-decor').forEach(n => n.remove());
|
||||||
|
colDecorState.length = 0;
|
||||||
|
document.querySelectorAll('.fullpage:not(.large-container)').forEach(col => {
|
||||||
|
const img1 = createColDecorImg(1);
|
||||||
|
const img2 = createColDecorImg(2);
|
||||||
|
layoutContainer.appendChild(img1);
|
||||||
|
layoutContainer.appendChild(img2);
|
||||||
|
colDecorState.push({ img1, img2, col });
|
||||||
|
});
|
||||||
|
positionColDecor();
|
||||||
|
}
|
||||||
|
|
||||||
|
function positionColDecor() {
|
||||||
|
if (!colDecorState.length) return;
|
||||||
|
const lcRect = layoutContainer.getBoundingClientRect();
|
||||||
|
const lcTopAbs = lcRect.top + window.scrollY;
|
||||||
|
const lcLeftAbs = lcRect.left + window.scrollX;
|
||||||
|
for (const entry of colDecorState) {
|
||||||
|
const { img1, img2, col } = entry;
|
||||||
|
const r = col.getBoundingClientRect();
|
||||||
|
const colH = r.height;
|
||||||
|
const m = colDecorMetrics(colH);
|
||||||
|
const stack2H = m.gapBottom + m.h2;
|
||||||
|
const stack1H = stack2H + m.gapBetween + m.h1;
|
||||||
|
const showBoth = stack1H <= colH * 0.5;
|
||||||
|
const showOne = !showBoth && stack2H <= colH * 0.3;
|
||||||
|
img1.style.display = showBoth ? 'block' : 'none';
|
||||||
|
img2.style.display = (showBoth || showOne) ? 'block' : 'none';
|
||||||
|
entry.visible1 = showBoth;
|
||||||
|
entry.visible2 = showBoth || showOne;
|
||||||
|
if (!showBoth && !showOne) continue;
|
||||||
|
const colBottomAbs = r.bottom + window.scrollY;
|
||||||
|
const leftRel = (r.left + window.scrollX) - lcLeftAbs;
|
||||||
|
const top2 = colBottomAbs - m.gapBottom - m.h2;
|
||||||
|
img2.style.top = (top2 - lcTopAbs) + 'px';
|
||||||
|
img2.style.left = leftRel + 'px';
|
||||||
|
img2.style.height = m.h2 + 'px';
|
||||||
|
// Référence scroll : motif centré dans le viewport.
|
||||||
|
entry.scrollRef2 = top2 + m.h2 / 2 - window.innerHeight / 2;
|
||||||
|
if (showBoth) {
|
||||||
|
const top1 = top2 - m.gapBetween - m.h1;
|
||||||
|
img1.style.top = (top1 - lcTopAbs) + 'px';
|
||||||
|
img1.style.left = leftRel + 'px';
|
||||||
|
img1.style.height = m.h1 + 'px';
|
||||||
|
entry.scrollRef1 = top1 + m.h1 / 2 - window.innerHeight / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Premier rendu du parallax après (re)position.
|
||||||
|
applyColDecorParallax();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parallax custom (sans Rellax) : remontée subtile, amplitude bornée,
|
||||||
|
// proportionnelle au scroll relatif à la position d'ancrage. À 0.15
|
||||||
|
// de vitesse, pour 100px de scroll au-delà de la référence, le motif
|
||||||
|
// monte de 15px ; clamp à ±30px évite tout débordement.
|
||||||
|
const COL_DECOR_PARALLAX_SPEED = 0.15;
|
||||||
|
const COL_DECOR_PARALLAX_AMP = 30;
|
||||||
|
let colDecorRafPending = false;
|
||||||
|
|
||||||
|
function applyColDecorParallax() {
|
||||||
|
const scrollY = window.scrollY || document.body.scrollTop || 0;
|
||||||
|
for (const { img1, img2, visible1, visible2, scrollRef1, scrollRef2 } of colDecorState) {
|
||||||
|
if (visible2 && scrollRef2 != null) {
|
||||||
|
const dY = clamp(-COL_DECOR_PARALLAX_AMP,
|
||||||
|
-(scrollY - scrollRef2) * COL_DECOR_PARALLAX_SPEED,
|
||||||
|
COL_DECOR_PARALLAX_AMP);
|
||||||
|
img2.style.transform = `translate3d(0, ${dY}px, 0) translateX(-100%)`;
|
||||||
|
}
|
||||||
|
if (visible1 && scrollRef1 != null) {
|
||||||
|
const dY = clamp(-COL_DECOR_PARALLAX_AMP,
|
||||||
|
-(scrollY - scrollRef1) * COL_DECOR_PARALLAX_SPEED,
|
||||||
|
COL_DECOR_PARALLAX_AMP);
|
||||||
|
img1.style.transform = `translate3d(0, ${dY}px, 0) translateX(-100%)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onColDecorScroll() {
|
||||||
|
if (colDecorRafPending) return;
|
||||||
|
colDecorRafPending = true;
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
colDecorRafPending = false;
|
||||||
|
applyColDecorParallax();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!document.body.dataset.colDecorScrollWired) {
|
||||||
|
document.body.addEventListener('scroll', onColDecorScroll, { passive: true });
|
||||||
|
document.body.dataset.colDecorScrollWired = 'true';
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Décors latéraux parallax v2.
|
// Décors latéraux parallax v2.
|
||||||
// Cloner le .decor-tile autant de fois que nécessaire pour couvrir
|
// Cloner le .decor-tile autant de fois que nécessaire pour couvrir
|
||||||
@@ -472,15 +605,30 @@
|
|||||||
rellax = new Rellax('.bgImg', { wrapper: 'body' });
|
rellax = new Rellax('.bgImg', { wrapper: 'body' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init initial : frises latérales (basées sur layout-container,
|
||||||
|
// mesure stable même sans images chargées) + Rellax. Les col-decor
|
||||||
|
// sont injectés et positionnés UNIQUEMENT au window.load — leur
|
||||||
|
// position dépend de getBoundingClientRect() de .fullpage qui n'est
|
||||||
|
// fiable qu'une fois toutes les images du contenu chargées (sinon
|
||||||
|
// Rellax cache un blockTop périmé et le motif dérive vers le bas
|
||||||
|
// sur les pages longues).
|
||||||
setupBackgroundTiles();
|
setupBackgroundTiles();
|
||||||
initRellax();
|
initRellax();
|
||||||
|
|
||||||
// Resize debouncé : recalcule le nombre de tiles, repart Rellax propre.
|
window.addEventListener('load', () => {
|
||||||
|
setupBackgroundTiles();
|
||||||
|
setupColDecor();
|
||||||
|
initRellax();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Resize debouncé : recalcule le nombre de tiles + col-decor,
|
||||||
|
// repart Rellax propre.
|
||||||
let bgResizeTimer = null;
|
let bgResizeTimer = null;
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener('resize', () => {
|
||||||
clearTimeout(bgResizeTimer);
|
clearTimeout(bgResizeTimer);
|
||||||
bgResizeTimer = setTimeout(() => {
|
bgResizeTimer = setTimeout(() => {
|
||||||
setupBackgroundTiles();
|
setupBackgroundTiles();
|
||||||
|
setupColDecor();
|
||||||
initRellax();
|
initRellax();
|
||||||
}, 200);
|
}, 200);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -63,3 +63,13 @@ $tile_height: 220vh;
|
|||||||
.decor-right-13 { top: 92%; height: 22vh; }
|
.decor-right-13 { top: 92%; height: 22vh; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Décors mid-left au pied gauche extérieur des .fullpage internes.
|
||||||
|
// Injection et positionnement en JS (cf. setupColDecor dans
|
||||||
|
// erabletheme.js) ; on gère uniquement la visibilité responsive ici.
|
||||||
|
.col-decor {
|
||||||
|
display: none;
|
||||||
|
@media (min-width: $breakpoint_tablet) {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user