PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.14
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.14
2.0.14 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 / scroll-reveal / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.14, at blocks/scroll-reveal/frontend.js

153 lines 7.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* Scroll Reveal — frontend */
2 (function () {
3 'use strict';
4
5 /* map animation name → { initial transform, optional extra } */
6 function getInitialTransform(animation, distance, scale, rotate) {
7 var d = distance + 'px';
8 switch (animation) {
9 case 'fade-up': return 'translateY(' + d + ')';
10 case 'fade-down': return 'translateY(-' + d + ')';
11 case 'fade-left': return 'translateX(' + d + ')';
12 case 'fade-right': return 'translateX(-' + d + ')';
13 case 'slide-up': return 'translateY(' + d + ')';
14 case 'slide-down': return 'translateY(-' + d + ')';
15 case 'slide-left': return 'translateX(' + d + ')';
16 case 'slide-right': return 'translateX(-' + d + ')';
17 case 'zoom-in': return 'scale(' + (scale / 100) + ')';
18 case 'zoom-out': return 'scale(' + (scale > 100 ? scale / 100 : 1.1) + ')';
19 case 'flip-left': return 'perspective(600px) rotateY(-90deg)';
20 case 'flip-right': return 'perspective(600px) rotateY(90deg)';
21 case 'rotate-in': return 'rotate(' + rotate + 'deg)';
22 case 'skew-up': return 'translateY(' + d + ') skewX(' + rotate + 'deg)';
23 case 'bounce-in': return 'scale(0.8)';
24 case 'fade-in':
25 default: return 'none';
26 }
27 }
28
29 function getRevealTransition(animation, easing, duration) {
30 var bounce = animation === 'bounce-in' ? 'cubic-bezier(0.34,1.56,0.64,1)' : easing;
31 return 'opacity ' + duration + 'ms ' + bounce + ', transform ' + duration + 'ms ' + bounce;
32 }
33
34 function applyInitial(el, animation, distance, scale, rotate, opacity) {
35 var transform = getInitialTransform(animation, distance, scale, rotate);
36 el.style.opacity = (opacity / 100).toString();
37 el.style.transform = transform;
38 el.style.willChange = 'opacity, transform';
39 }
40
41 function applyRevealed(el, transition, delay) {
42 el.style.transition = transition;
43 if (delay) { el.style.transitionDelay = delay + 'ms'; }
44 el.style.opacity = '1';
45 el.style.transform = 'none';
46 }
47
48 function init() {
49 var motionPreference = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)');
50 // Content stays readable when motion is unwanted or observers are unavailable.
51 if ((motionPreference && motionPreference.matches) || typeof window.IntersectionObserver !== 'function') { return; }
52 var animated = [];
53 var observers = [];
54
55 function revealWithoutMotion() {
56 if (!motionPreference.matches) { return; }
57 observers.forEach(function (observer) { observer.disconnect(); });
58 animated.forEach(function (element) {
59 element.style.transition = 'none';
60 element.style.transitionDelay = '0ms';
61 element.style.opacity = '1';
62 element.style.transform = 'none';
63 element.style.willChange = '';
64 });
65 }
66
67 function option(wrap, name, fallback, min, max) {
68 var n = parseFloat(wrap.getAttribute('data-' + name));
69 return Number.isFinite(n) ? Math.min(max, Math.max(min, n)) : fallback;
70 }
71
72 document.querySelectorAll('.bksr-wrap[data-animation]').forEach(function (wrap) {
73 if (wrap._bksrInit) { return; }
74 wrap._bksrInit = true;
75
76 var animation = wrap.getAttribute('data-animation') || 'fade-up';
77 var duration = option(wrap, 'duration', 600, 0, 10000);
78 var delay = option(wrap, 'delay', 0, 0, 10000);
79 var easing = wrap.getAttribute('data-easing') || 'ease';
80 var distance = option(wrap, 'distance', 32, 0, 1000);
81 var scale = option(wrap, 'scale', 95, 0, 300);
82 var rotate = option(wrap, 'rotate', 0, -360, 360);
83 var opacity = option(wrap, 'opacity', 0, 0, 100);
84 var threshold = option(wrap, 'threshold', 15, 0, 100) / 100;
85 var once = wrap.getAttribute('data-once') !== '0';
86 var stagger = wrap.getAttribute('data-stagger') === '1';
87 var staggerDelay = option(wrap, 'stagger-delay', 100, 0, 10000);
88 // A long composition cannot fit its requested intersection ratio in
89 // the viewport. Cap it to a reachable ratio so it can still reveal.
90 threshold = Math.min(threshold, window.innerHeight / Math.max(1, wrap.getBoundingClientRect().height) * 0.9);
91
92 var transition = getRevealTransition(animation, easing, duration);
93
94 if (stagger) {
95 /* animate each direct child individually */
96 var children = Array.prototype.slice.call(wrap.children);
97 children.forEach(function (child) {
98 child.classList.add('bksr-child-reveal');
99 animated.push(child);
100 applyInitial(child, animation, distance, scale, rotate, opacity);
101 });
102
103 var observer = new IntersectionObserver(function (entries) {
104 entries.forEach(function (entry) {
105 if (!entry.isIntersecting) { return; }
106 var kids = Array.prototype.slice.call(entry.target.children);
107 kids.forEach(function (child, i) {
108 applyRevealed(child, transition, delay + i * staggerDelay);
109 });
110 if (once) { observer.unobserve(entry.target); }
111 });
112 }, { threshold: threshold });
113
114 observer.observe(wrap);
115 observers.push(observer);
116
117 } else {
118 /* animate whole wrapper */
119 applyInitial(wrap, animation, distance, scale, rotate, opacity);
120 animated.push(wrap);
121
122 var obs = new IntersectionObserver(function (entries) {
123 entries.forEach(function (entry) {
124 if (!entry.isIntersecting) {
125 if (!once) {
126 /* reset */
127 applyInitial(entry.target, animation, distance, scale, rotate, opacity);
128 entry.target.style.transition = 'none';
129 }
130 return;
131 }
132 applyRevealed(entry.target, transition, delay);
133 if (once) { obs.unobserve(entry.target); }
134 });
135 }, { threshold: threshold });
136
137 obs.observe(wrap);
138 observers.push(obs);
139 }
140 });
141 if (motionPreference && animated.length) {
142 if (motionPreference.addEventListener) { motionPreference.addEventListener('change', revealWithoutMotion); }
143 else if (motionPreference.addListener) { motionPreference.addListener(revealWithoutMotion); }
144 }
145 }
146
147 if (document.readyState === 'loading') {
148 document.addEventListener('DOMContentLoaded', init);
149 } else {
150 init();
151 }
152 }());
153