vevet
Version:
Vevet is a JavaScript library for creative development that simplifies crafting rich interactions like split text animations, carousels, marquees, preloading, and more.
334 lines • 12.5 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.SnapWheel = void 0;
var initVevet_1 = require("../../../../global/initVevet");
var isNumber_1 = require("../../../../internal/isNumber");
var utils_1 = require("../../../../utils");
var SnapLogic_1 = require("../SnapLogic");
var deltasCount = 6;
var SnapWheel = /** @class */ (function (_super) {
__extends(SnapWheel, _super);
function SnapWheel(snap) {
var _this = _super.call(this, snap) || this;
/** Detects if wheel event is started */
_this._hasStarted = false;
/** Deltas history */
_this._deltas = [];
/** Last time wheel event was fired */
_this._lastWheelTime = 0;
var listener = (0, utils_1.addEventListener)(snap.eventsEmitter, 'wheel', function (event) {
return _this._handleWheel(event);
});
_this.addDestructor(function () {
listener();
if (_this._debounceEnd) {
clearTimeout(_this._debounceEnd);
}
});
return _this;
}
Object.defineProperty(SnapWheel.prototype, "track", {
/** Snap track */
get: function () {
// @ts-ignore
// eslint-disable-next-line no-underscore-dangle
return this.snap._track;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapWheel.prototype, "absDeltas", {
/** Get absolute deltas */
get: function () {
return this._deltas.map(function (d) { return Math.abs(d); });
},
enumerable: false,
configurable: true
});
/**
* Handles wheel events
*/
SnapWheel.prototype._handleWheel = function (event) {
var _this = this;
var _a = this.snap, props = _a.props, axis = _a.axis;
if (!props.wheel) {
return;
}
event.preventDefault();
// Get delta
var wheelData = (0, utils_1.normalizeWheel)(event);
var wheelAxis = props.wheelAxis === 'auto' ? axis : props.wheelAxis;
var delta = wheelAxis === 'x' ? wheelData.pixelX : wheelData.pixelY;
// Start
this._handleStart(delta);
// Start
this._handleMove(delta, event);
// Debounce End
if (this._debounceEnd) {
clearTimeout(this._debounceEnd);
}
// End callback
this._debounceEnd = setTimeout(function () { return _this._handleEnd(); }, 200);
};
/** Handle wheel start */
SnapWheel.prototype._handleStart = function (delta) {
if (this._hasStarted || Math.abs(delta) < 2) {
return;
}
this._hasStarted = true;
this.snap.callbacks.emit('wheelStart', undefined);
};
/** Handle wheel move */
SnapWheel.prototype._handleMove = function (delta, event) {
if (!this._hasStarted) {
return;
}
var _a = this.snap, props = _a.props, callbacks = _a.callbacks;
// Save delta
this._addDelta(delta);
// Move callback
callbacks.emit('wheel', event);
// Handle wheel logic
if (props.followWheel) {
this._handleFollow(delta);
}
else {
this._handleNoFollow(delta);
}
};
/** Handle `followWheel=true` */
SnapWheel.prototype._handleFollow = function (delta) {
var _a = this, snap = _a.snap, track = _a.track;
// Cancel snap transition
track.cancelTransition();
// Update track target
track.iterateTarget(delta * snap.props.wheelSpeed);
track.clampTarget();
};
/** Handle `followWheel=false` */
SnapWheel.prototype._handleNoFollow = function (deltaProp) {
// vars
var _a = this, snap = _a.snap, track = _a.track, isTouchPad = _a.isTouchPad, isGainingDelta = _a.isGainingDelta;
var props = snap.props, activeSlide = snap.activeSlide;
var delta = deltaProp * props.wheelSpeed;
// Detect wheel throttling
if (this._detectNoFollowThrottle()) {
return;
}
// Detect if need to throttle or follow
var shouldFollow = false;
var isThrottled = true;
if (!shouldFollow) {
if (snap.isSlideScrolling) {
if (activeSlide.coord === 0) {
if (delta > 0) {
shouldFollow = true;
}
}
else if (activeSlide.coord ===
snap.containerSize - activeSlide.size) {
if (delta < 0) {
shouldFollow = true;
}
}
else {
shouldFollow = true;
isThrottled = false;
}
}
}
// Throttle
if (isThrottled) {
if (!isTouchPad ||
(isTouchPad && (isGainingDelta || this.absDeltas.length === 1))) {
var direction = Math.sign(delta);
if (shouldFollow) {
snap.cancelTransition();
track.iterateTarget(direction);
track.clampTarget();
if (!isTouchPad) {
track.current = track.target;
}
}
else if (direction === 1) {
if (!props.loop && snap.activeIndex === snap.slides.length - 1) {
if (!props.rewind) {
return;
}
}
this._lastWheelTime = +new Date();
snap.next();
}
else {
if (!props.loop && snap.activeIndex === 0) {
if (!props.rewind) {
return;
}
}
this._lastWheelTime = +new Date();
snap.prev();
}
}
return;
}
// Follow wheel
if (shouldFollow) {
snap.cancelTransition();
var deltaWithSpeed = delta;
var start = Math.min.apply(Math, activeSlide.magnets);
var end = Math.max.apply(Math, activeSlide.magnets);
var loopedTarget = track.loopCoord(track.target);
var clampedLoopedTarget = (0, utils_1.clamp)(loopedTarget + deltaWithSpeed, start, end);
track.target = track.target + clampedLoopedTarget - loopedTarget;
track.clampTarget();
}
};
/** Detect if wheel should be throttled */
SnapWheel.prototype._detectNoFollowThrottle = function () {
var _a = this, isTouchPad = _a.isTouchPad, snap = _a.snap;
var wheelThrottle = snap.props.wheelThrottle;
var timeDiff = +new Date() - this._lastWheelTime;
// NUMBER
if ((0, isNumber_1.isNumber)(wheelThrottle)) {
return timeDiff < wheelThrottle;
}
// AUTO
if (isTouchPad) {
return snap.isTransitioning;
}
var visibleScrollableSlides = snap.scrollableSlides.filter(function (slide) { return slide.isVisible; });
if (visibleScrollableSlides.length && snap.isTransitioning) {
return true;
}
if (timeDiff < 500) {
return true;
}
return false;
};
/** Handle wheel end */
SnapWheel.prototype._handleEnd = function () {
if (!this._hasStarted) {
return;
}
var snap = this.snap;
var props = snap.props, activeSlide = snap.activeSlide;
var lastThreeDeltas = this._deltas.slice(-3).reduce(function (a, b) { return a + b; }, 0);
// Reset states
this._deltas = [];
this._hasStarted = false;
// Stick to the nearest magnet
if (!props.freemode || props.freemode === 'sticky') {
if (props.followWheel && props.stickOnWheelEnd) {
// Classic stick when scrolling stops
var slideThreshold = Math.abs(props.stickOnWheelEndThreshold) / activeSlide.size;
if (activeSlide.progress > slideThreshold &&
!snap.isSlideScrolling &&
lastThreeDeltas > 0) {
snap.next();
}
else if (activeSlide.progress < -slideThreshold &&
!snap.isSlideScrolling &&
lastThreeDeltas < 0) {
snap.prev();
}
else {
snap.stick();
}
}
else if (!props.followWheel && !snap.isTransitioning) {
// Stick if something goes wrong when followWheel is disabled
snap.stick();
}
}
snap.callbacks.emit('wheelEnd', undefined);
};
/** Save delta */
SnapWheel.prototype._addDelta = function (delta) {
if (this._deltas.length >= deltasCount) {
this._deltas.shift();
}
this._deltas.push(delta);
};
Object.defineProperty(SnapWheel.prototype, "isTouchPad", {
/** Detect if touchpad */
get: function () {
return !this.isStableDelta || this.isSmallDelta;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapWheel.prototype, "isStableDelta", {
/** Detects if deltas are stable */
get: function () {
var deltas = this.absDeltas;
var precision = 0.8;
// get difference between deltas
var diffs = deltas.map(function (d, i) {
var prev = deltas[i - 1];
if (!deltas[i - 1]) {
return 0;
}
return d - prev;
});
var zeroDiffs = diffs.filter(function (d) { return d === 0; });
return zeroDiffs.length > diffs.length * precision;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapWheel.prototype, "isSmallDelta", {
/** Detects if the latest delta is small */
get: function () {
var deltas = this.absDeltas;
if (deltas.length === 0) {
return true;
}
var last = deltas[deltas.length - 1];
return last < 50;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapWheel.prototype, "isGainingDelta", {
/** Detect if delta is gaining its value */
get: function () {
var vevet = (0, initVevet_1.initVevet)();
var deltas = this.absDeltas;
var precision = vevet.osName.includes('window') ? 1.5 : 1.2;
if (deltas.length < deltasCount) {
return false;
}
var lastDeltas = deltas.slice(-deltasCount);
var half1 = lastDeltas.slice(0, Math.floor(lastDeltas.length / 2));
var half2 = lastDeltas.slice(Math.floor(lastDeltas.length / 2));
var avg1 = this._getAverage(half1);
var avg2 = this._getAverage(half2);
var isGaining = avg2 > avg1 * precision;
return isGaining;
},
enumerable: false,
configurable: true
});
/** Get average value in an array */
SnapWheel.prototype._getAverage = function (array) {
return array.length ? array.reduce(function (a, b) { return a + b; }, 0) / array.length : 0;
};
return SnapWheel;
}(SnapLogic_1.SnapLogic));
exports.SnapWheel = SnapWheel;
//# sourceMappingURL=index.js.map