PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / parallax-section / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/parallax-section/frontend.js

73 lines 2.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* Parallax Section — frontend */
2 (function () {
3 'use strict';
4
5 var reducedMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
6
7 /* ── collect all parallax sections ──────────────────────────────────────── */
8 var sections = [];
9
10 function collectSections() {
11 sections = Array.prototype.slice.call(
12 document.querySelectorAll('.bkps-outer[data-parallax="1"]')
13 ).map(function (outer) {
14 var bg = outer.querySelector('.bkps-bg');
15 var speed = parseFloat(outer.getAttribute('data-speed')) || 0.4;
16 return { outer: outer, bg: bg, speed: speed };
17 }).filter(function (s) { return s.bg; });
18 }
19
20 /* ── rAF update loop ─────────────────────────────────────────────────────── */
21 var ticking = false;
22
23 function updateAll() {
24 var scrollY = window.pageYOffset;
25
26 sections.forEach(function (s) {
27 var rect = s.outer.getBoundingClientRect();
28 var vh = window.innerHeight;
29
30 /* only update when on screen */
31 if (rect.bottom < 0 || rect.top > vh) { return; }
32
33 /* relative scroll position: 0 when section top at screen bottom, 1 when section bottom at screen top */
34 var progress = (scrollY + vh - (s.outer.offsetTop)) / (vh + s.outer.offsetHeight);
35 progress = Math.max(0, Math.min(1, progress));
36
37 /* movement range: ±(speed * 30)% of outer height */
38 var shift = (progress - 0.5) * s.speed * s.outer.offsetHeight;
39
40 s.bg.style.transform = 'translate3d(0, ' + shift + 'px, 0)';
41 });
42 ticking = false;
43 }
44
45 function onScroll() {
46 if (!ticking) {
47 ticking = true;
48 requestAnimationFrame(updateAll);
49 }
50 }
51
52 /* ── init ────────────────────────────────────────────────────────────────── */
53 function init() {
54 if (reducedMotion) { return; }
55 collectSections();
56 if (!sections.length) { return; }
57
58 window.addEventListener('scroll', onScroll, { passive: true });
59 window.addEventListener('resize', function () {
60 collectSections(); /* recollect offsets on resize */
61 updateAll();
62 });
63 /* initial position */
64 requestAnimationFrame(updateAll);
65 }
66
67 if (document.readyState === 'loading') {
68 document.addEventListener('DOMContentLoaded', init);
69 } else {
70 init();
71 }
72 }());
73