chore: complete update
This commit is contained in:
69
resources/js/modules/scrollfx/ScrollTrigger.js
Normal file
69
resources/js/modules/scrollfx/ScrollTrigger.js
Normal file
@@ -0,0 +1,69 @@
|
||||
// src/resources/js/scrollfx/ScrollTrigger.js
|
||||
|
||||
export default class ScrollTrigger {
|
||||
constructor(config) {
|
||||
this.element = this.resolveElement(config.element);
|
||||
this.target = config.target
|
||||
? this.element.querySelector(config.target)
|
||||
: this.element;
|
||||
|
||||
if (config.target && !this.target) {
|
||||
throw new Error(`Target selector '${config.target}' not found inside element '${config.element}'.`);
|
||||
}
|
||||
|
||||
this.start = config.start || 'top 80%';
|
||||
this.end = config.end || 'bottom 20%';
|
||||
this.scrub = config.scrub || false;
|
||||
this.onEnter = config.onEnter || null;
|
||||
this.onLeave = config.onLeave || null;
|
||||
this.onUpdate = config.onUpdate || null;
|
||||
|
||||
this._wasVisible = false;
|
||||
this._progress = 0;
|
||||
}
|
||||
|
||||
resolveElement(input) {
|
||||
if (typeof input === 'string') {
|
||||
const els = document.querySelectorAll(input);
|
||||
if (els.length === 1) return els[0];
|
||||
throw new Error(`Selector '${input}' matched ${els.length} elements, expected exactly 1.`);
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
getScrollProgress(viewportHeight) {
|
||||
const rect = this.element.getBoundingClientRect();
|
||||
const startPx = this.parsePosition(this.start, viewportHeight);
|
||||
const endPx = this.parsePosition(this.end, viewportHeight);
|
||||
const scrollRange = endPx - startPx;
|
||||
const current = rect.top - startPx;
|
||||
return 1 - Math.min(Math.max(current / scrollRange, 0), 1);
|
||||
}
|
||||
|
||||
parsePosition(pos, viewportHeight) {
|
||||
const [edge, value] = pos.split(' ');
|
||||
const edgeOffset = edge === 'top' ? 0 : viewportHeight;
|
||||
const percentage = parseFloat(value) / 100;
|
||||
return edgeOffset - viewportHeight * percentage;
|
||||
}
|
||||
|
||||
update(viewportHeight) {
|
||||
const rect = this.element.getBoundingClientRect();
|
||||
const inViewport = rect.bottom > 0 && rect.top < viewportHeight;
|
||||
|
||||
if (inViewport && !this._wasVisible) {
|
||||
this._wasVisible = true;
|
||||
if (this.onEnter) this.onEnter(this.target);
|
||||
}
|
||||
|
||||
if (!inViewport && this._wasVisible) {
|
||||
this._wasVisible = false;
|
||||
if (this.onLeave) this.onLeave(this.target);
|
||||
}
|
||||
|
||||
if (this.scrub && inViewport) {
|
||||
const progress = this.getScrollProgress(viewportHeight);
|
||||
if (this.onUpdate) this.onUpdate(this.target, progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user