PageSourceSearch

https://superacesso.info/wp-content/plugins/wiloke-3d-parallax/src/Source/script-3d-hover.js?ver=1.0.3

js superacesso.info collected 2026-10-09 21:57:33 UTC 12,955 bytes, 544 lines download raw bytes

1(function () {
2	"use strict";
3	
4	const DEFAULT_FPS = 60;
5	const DT_FPS = 1000 / DEFAULT_FPS;
6	
7	const easings = {
8		linear: (t) => t,
9		ease: (t) => 0.5 * (1 - Math.cos(Math.PI * t)),
10		easeInQuad: (t) => t * t,
11		easeOutQuad: (t) => t * (2 - t),
12		easeInOutQuad: (t) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t),
13		easeInCubic: (t) => t * t * t,
14		easeOutCubic: (t) => --t * t * t + 1,
15		easeInOutCubic: (t) =>
16			t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1,
17		easeInQuart: (t) => t * t * t * t,
18		easeOutQuart: (t) => 1 - --t * t * t * t,
19		easeInOutQuart: (t) =>
20			t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t,
21		easeInQuint: (t) => t * t * t * t * t,
22		easeOutQuint: (t) => 1 + --t * t * t * t * t,
23		easeInOutQuint: (t) =>
24			t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t,
25		easeOutBounce: (t) => {
26			const n1 = 7.5625;
27			const d1 = 2.75;
28			
29			if (t < 1 / d1) {
30				return n1 * t * t;
31			}
32			if (t < 2 / d1) {
33				return n1 * (t -= 1.5 / d1) * t + 0.75;
34			}
35			if (t < 2.5 / d1) {
36				return n1 * (t -= 2.25 / d1) * t + 0.9375;
37			}
38			return n1 * (t -= 2.625 / d1) * t + 0.984375;
39		},
40		easeInBounce: (t) => 1 - easings.easeOutBounce(1 - t),
41		easeOutBack: (t) => {
42			const c1 = 1.70158;
43			const c3 = c1 + 1;
44			
45			return 1 + c3 * (t - 1) ** 3 + c1 * (t - 1) ** 2;
46		},
47		easeInBack: (t) => {
48			const c1 = 1.70158;
49			const c3 = c1 + 1;
50			
51			return c3 * t * t * t - c1 * t * t;
52		},
53		easeInOut: (t) =>
54			t < 0.5
55				? easings.easeInBack(t * 2) / 2
56				: easings.easeOutBack(t * 2 - 1) / 2 + 0.5,
57		easeInElastic: (t) => {
58			const c4 = (2 * Math.PI) / 3;
59			return t === 0
60				? 0
61				: t === 1
62					? 1
63					: -(2 ** (10 * t - 10)) * Math.sin((t * 10 - 10.75) * c4);
64		},
65		easeOutElastic: (t) => {
66			const c4 = (2 * Math.PI) / 3;
67			return t === 0
68				? 0
69				: t === 1
70					? 1
71					: 2 ** (-10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
72		},
73		spring: (t) => 1 - Math.cos(t * 4.5 * Math.PI) * Math.exp(-t * 6),
74		decay: (t) => 1 - Math.exp(-t * 6),
75		bezier: (x1, y1, x2, y2) => (t) => {
76			const ax = 3 * x1 - 3 * x2 + 1;
77			const bx = 3 * x2 - 6 * x1;
78			const cx = 3 * x1;
79			const ay = 3 * y1 - 3 * y2 + 1;
80			const by = 3 * y2 - 6 * y1;
81			const cy = 3 * y1;
82			
83			// eslint-disable-next-line @typescript-eslint/no-shadow
84			const sampleCurveX = (t) => ((ax * t + bx) * t + cx) * t;
85			
86			const sampleCurveY = (t) => ((ay * t + by) * t + cy) * t;
87			
88			const sampleCurveDerivativeX = (t) => (3 * ax * t + 2 * bx) * t + cx;
89			
90			const solveCurveX = (x, epsilon) => {
91				let t0;
92				let t1;
93				let t2;
94				let x2;
95				let d2;
96				let i;
97				
98				for (t2 = x, i = 0; i < 8; i++) {
99					x2 = sampleCurveX(t2) - x;
100					if (Math.abs(x2) < epsilon) {
101						return t2;
102					}
103					d2 = sampleCurveDerivativeX(t2);
104					if (Math.abs(d2) < 1e-6) {
105						break;
106					}
107					t2 -= x2 / d2;
108				}
109				
110				t0 = 0;
111				t1 = 1;
112				t2 = x;
113				
114				if (t2 < t0) {
115					return t0;
116				}
117				if (t2 > t1) {
118					return t1;
119				}
120				
121				while (t0 < t1) {
122					x2 = sampleCurveX(t2);
123					if (Math.abs(x2 - x) < epsilon) {
124						return t2;
125					}
126					if (x > x2) {
127						t0 = t2;
128					} else {
129						t1 = t2;
130					}
131					t2 = (t1 - t0) * 0.5 + t0;
132				}
133				
134				return t2;
135			};
136			
137			return sampleCurveY(solveCurveX(t, 1 / 200));
138		},
139	};
140	
141	function interpolate({
142		                     inputRange,
143		                     outputRange,
144		                     value,
145		                     easing = (value) => value,
146		                     reverseEasing = false,
147	                     }) {
148		const sortedRanges = inputRange
149			.map((_, i) => ({input: inputRange[i], output: outputRange[i]}))
150			.sort((a, b) => a.input - b.input);
151		const sortedInputRange = sortedRanges.map(({input}) => input);
152		const sortedOutputRange = sortedRanges.map(({output}) => output);
153		
154		if (value <= sortedInputRange[0]) {
155			return sortedOutputRange[0];
156		}
157		
158		if (value >= sortedInputRange[sortedInputRange.length - 1]) {
159			return sortedOutputRange[sortedOutputRange.length - 1];
160		}
161		
162		let i = 0;
163		for (const inputValue of sortedInputRange) {
164			if (inputValue < value) {
165				i++;
166			}
167		}
168		
169		const j = i - 1;
170		
171		let ratio =
172			(value - sortedInputRange[j]) / (sortedInputRange[i] - sortedInputRange[j]);
173		if (typeof easing === "function") {
174			if (reverseEasing) {
175				ratio = 1 - easing(1 - ratio);
176			} else {
177				ratio = easing(ratio);
178			}
179		}
180		return sortedOutputRange[j] * (1 - ratio) + sortedOutputRange[i] * ratio;
181	}
182	
183	function getWindow(el) {
184		return el.nodeType === 9 && el.defaultView;
185	}
186	
187	function offset(el) {
188		const doc = el?.ownerDocument;
189		const docElem = doc.documentElement;
190		const win = getWindow(doc);
191		let box = {top: 0, left: 0};
192		
193		if (!doc) {
194			return {
195				top: 0,
196				left: 0,
197			};
198		}
199		
200		if (typeof el.getBoundingClientRect !== typeof undefined) {
201			box = el.getBoundingClientRect();
202		}
203		
204		return {
205			top: box.top + win.scrollY - docElem.clientTop,
206			left: box.left + win.scrollX - docElem.clientLeft,
207		};
208	}
209	
210	function objectParse(value) {
211		const val = value.trim();
212		if (/^{|\[/g.test(val)) {
213			try {
214				const fn = new Function(`return ${val}`);
215				const obj = fn();
216				return JSON.parse(JSON.stringify(obj));
217			} catch {
218				if (/^\[/g.test(val)) {
219					return [];
220				}
221				return {};
222			}
223		} else {
224			return {};
225		}
226	}
227	
228	const lerp = (p1, p2, t) => {
229		return p1 + (p2 - p1) * t;
230	};
231	
232	function map(array, callback) {
233		const result = [];
234		for (let i = 0; i < array.length; i++) {
235			result.push(callback(array[i], i, array));
236		}
237		return result;
238	}
239	
240	function kebabToCamel(value) {
241		return value.replace(/([-]\w)/g, (g) => g[1].toUpperCase());
242	}
243	
244	function getValue(value, type) {
245		switch (type) {
246			case "string":
247				return value;
248			case "number":
249				return Number(value);
250			case "boolean":
251				return value === "true" || value === "";
252			case "object":
253				return objectParse(value);
254			case "array":
255				return objectParse(value);
256			default:
257				return value;
258		}
259	}
260	
261	function getAttrs(
262		el,
263		{prefix = "v-", pick, types, camelCase = true, propTransformer} = {}
264	) {
265		let result = {};
266		
267		if (el == null) {
268			return result;
269		}
270		
271		const attrs = Array.from(el.attributes);
272		if (pick == null) {
273			pick = map(attrs, (attr) => attr.name);
274		}
275		for (const attr of attrs) {
276			if (!attr.name.startsWith(prefix)) {
277				continue;
278			}
279			let name = camelCase
280				? kebabToCamel(attr.name)
281				: attr.name.replace(prefix, "");
282			const type = types?.[name];
283			if (attr.value != null && pick?.includes(name)) {
284				if (typeof propTransformer === "function") {
285					name = propTransformer(name);
286				}
287				if (!!types && type != null) {
288					result = {...result, [name]: getValue(attr.value, type)};
289				} else {
290					result = {...result, [name]: attr.value};
291				}
292			}
293		}
294		return result;
295	}
296	
297	class FrameManager {
298		frameId;
299		keepAliveFrameId;
300		lastTimestamp;
301		frames;
302		keepAliveFrames;
303		defaultTimestep;
304		
305		constructor() {
306			this.frameId = null;
307			this.keepAliveFrameId = null;
308			this.lastTimestamp = null;
309			this.frames = [];
310			this.keepAliveFrames = [];
311			this.defaultTimestep = (1 / 60) * 1000;
312		}
313		
314		handleFrameLoop = (timestamp) => {
315			if (this.lastTimestamp) {
316				const delta = timestamp - this.lastTimestamp;
317				this.keepAliveFrames.forEach((frame) =>
318					frame.call(this, {delta, timestamp})
319				);
320			}
321			this.lastTimestamp = timestamp;
322			if (this.keepAliveFrameId) {
323				cancelAnimationFrame(this.keepAliveFrameId);
324			}
325			this.keepAliveFrameId = requestAnimationFrame(this.handleFrameLoop);
326		};
327		
328		handleFrame = (timestamp) => {
329			this.frames.forEach((frame) =>
330				frame.call(this, {delta: this.defaultTimestep, timestamp})
331			);
332		};
333		
334		getFrames = () => {
335			return this.frames;
336		};
337		
338		add = (frame, keepAlive = false) => {
339			this.cancelFrame();
340			if (!this.frames.includes(frame)) {
341				this.frames.push(frame);
342			}
343			if (keepAlive && !this.keepAliveFrames.includes(frame)) {
344				this.keepAliveFrames.push(frame);
345			}
346			this.start();
347			
348			return this;
349		};
350		
351		start = () => {
352			this.frameId = requestAnimationFrame(this.handleFrame);
353			this.keepAliveFrameId = requestAnimationFrame(this.handleFrameLoop);
354		};
355		
356		cancelFrame = () => {
357			if (this.frameId != null) {
358				cancelAnimationFrame(this.frameId);
359				this.frameId = null;
360			}
361			if (this.keepAliveFrameId != null) {
362				cancelAnimationFrame(this.keepAliveFrameId);
363				this.keepAliveFrameId = null;
364			}
365		};
366		
367		stopFrame = (frames, frame) => {
368			const taskIndex = frames.indexOf(frame);
369			if (taskIndex !== -1) {
370				frames.splice(taskIndex, 1);
371			}
372			if (frames.length === 0) {
373				this.cancelFrame();
374				this.lastTimestamp = null;
375			}
376		};
377		
378		remove = (frame) => {
379			this.stopFrame(this.frames, frame);
380			this.stopFrame(this.keepAliveFrames, frame);
381			
382			return this;
383		};
384		
385		clear = () => {
386			this.frames = [];
387			this.keepAliveFrames = [];
388			this.cancelFrame();
389			this.lastTimestamp = null;
390			
391			return this;
392		};
393	}
394	
395	const frameManager = new FrameManager();
396	
397	class ParallaxHover extends HTMLElement {
398		shadow = this.attachShadow({mode: "open"});
399		
400		providerEl = null;
401		
402		targetValueX = 0;
403		
404		targetValueY = 0;
405		
406		currentValueX = 0;
407		
408		currentValueY = 0;
409		
410		static defaultOptions = {
411			vStrength: 100,
412			vResetPosition: true,
413			v3d: false,
414		};
415		
416		constructor() {
417			super();
418			frameManager.add(this.handleFrameSyncUpdate, true);
419		}
420		
421		get options() {
422			const options = getAttrs(this, {
423				pick: ["vStrength", "vResetPosition", "v3d"],
424				types: {
425					vStrength: "number",
426					vResetPosition: "boolean",
427					v3d: "boolean",
428				},
429			});
430			
431			return {
432				...ParallaxHover.defaultOptions,
433				...options,
434			};
435		}
436		
437		handleParallax = (delta) => {
438			const {vStrength, v3d} = this.options;
439			let slowDown = delta / DT_FPS;
440			const slowDownRounded = Math.round(slowDown);
441			if (slowDownRounded >= 1) {
442				slowDown = slowDownRounded;
443			}
444			const lerpEase = Number(
445				this.providerEl?.getAttribute("v-lerp-ease") || "0.08"
446			);
447			const valueX = lerp(
448				this.currentValueX,
449				this.targetValueX,
450				lerpEase * slowDown
451			);
452			const valueY = lerp(
453				this.currentValueY,
454				this.targetValueY,
455				lerpEase * slowDown
456			);
457			const innerEl = this.shadow.querySelector("v-parallax-hover-inner");
458			if (v3d) {
459				const constant = 4;
460				innerEl.style.transformStyle = "preserve-3d";
461				innerEl.style.transform = `perspective(2000px) rotateX(${
462					(-valueY / constant) * vStrength
463				}deg) rotateY(${(valueX / constant) * vStrength}deg)`;
464			} else {
465				innerEl.style.transform = `translate3d(${valueX * vStrength}px, ${
466					valueY * vStrength
467				}px, 0)`;
468			}
469			this.currentValueX = valueX;
470			this.currentValueY = valueY;
471		};
472		
473		handleFrameSyncUpdate = ({delta}) => {
474			const diffX = Math.abs(this.targetValueX - this.currentValueX);
475			const diffY = Math.abs(this.targetValueY - this.currentValueY);
476			if (diffX < 0.001 && diffY < 0.001) {
477				return;
478			}
479			
480			this.handleParallax(delta);
481		};
482		
483		setTargetValue = (event, left, top, width, height) => {
484			const centerX = offset(this).left + this.offsetWidth / 2;
485			const centerY = offset(this).top + this.offsetHeight / 2;
486			this.targetValueX = interpolate({
487				value: event.pageX - left,
488				inputRange: [0, centerX - left, width],
489				outputRange: [-1, 0, 1],
490			});
491			this.targetValueY = interpolate({
492				value: event.pageY - top,
493				inputRange: [0, centerY - top, height],
494				outputRange: [-1, 0, 1],
495			});
496		};
497		
498		handleMouseMove = (event) => {
499			const providerLeft = offset(this.providerEl).left;
500			const providerTop = offset(this.providerEl).top;
501			const providerWidth = this.providerEl.offsetWidth;
502			const providerHeight = this.providerEl.offsetHeight;
503			this.setTargetValue(
504				event,
505				providerLeft,
506				providerTop,
507				providerWidth,
508				providerHeight
509			);
510		};
511		
512		handleMouseLeave = () => {
513			const {vResetPosition} = this.options;
514			if (vResetPosition) {
515				this.targetValueX = 0;
516				this.targetValueY = 0;
517			}
518		};
519		
520		connectedCallback() {
521			this.providerEl = this.closest("v-parallax");
522			if (!this.providerEl) {
523				throw new Error(
524					`The v-parallax-hover component must be a child of v-parallax`
525				);
526			}
527			if (!this.shadow.innerHTML) {
528				this.shadow.innerHTML = `<v-parallax-hover-inner style="display: block"><slot></slot></v-parallax-hover-inner>`;
529			}
530			this.handleParallax((1 / 60) * 1000);
531			this.providerEl.addEventListener("mousemove", this.handleMouseMove);
532			this.providerEl.addEventListener("mouseleave", this.handleMouseLeave);
533		}
534		
535		disconnectedCallback() {
536			frameManager.remove(this.handleFrameSyncUpdate);
537			this.providerEl?.removeEventListener("mousemove", this.handleMouseMove);
538			this.providerEl?.removeEventListener("mouseleave", this.handleMouseLeave);
539		}
540	}
541	
542	customElements.define("v-parallax-hover", ParallaxHover);
543	
544})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.