vevet
Version:
Vevet is a JavaScript library for creative development that simplifies crafting rich interactions like split text animations, carousels, marquees, preloading, and more.
363 lines • 14.1 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.SnapTrack = void 0;
var Raf_1 = require("../../../../components/Raf");
var Timeline_1 = require("../../../../components/Timeline");
var isNumber_1 = require("../../../../internal/isNumber");
var utils_1 = require("../../../../utils");
var math_1 = require("../../../../utils/math");
var props_1 = require("../../props");
var SnapLogic_1 = require("../SnapLogic");
var SnapTrack = /** @class */ (function (_super) {
__extends(SnapTrack, _super);
function SnapTrack(snap) {
var _this = _super.call(this, snap) || this;
/** Interpolation influence */
_this._influence = {
current: 0,
target: 0,
};
/** The current track value */
_this._current = 0;
/** The target track value */
_this._target = 0;
// Create the animation frame
_this._raf = new Raf_1.Raf();
_this._raf.on('frame', function () { return _this._handleRaf(); });
_this._raf.on('play', function () { return snap.callbacks.emit('rafPlay', undefined); });
_this._raf.on('pause', function () { return snap.callbacks.emit('rafPause', undefined); });
// Destroy raf
_this.addDestructor(function () { return _this._raf.destroy(); });
// Destroy timeline
_this.addDestructor(function () { return _this.cancelTransition(); });
return _this;
}
Object.defineProperty(SnapTrack.prototype, "isInterpolated", {
/** Whether the track is interpolated */
get: function () {
return this.current === this.target && this._influence.current === 0;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "influence", {
/** Gets the interpolation influence */
get: function () {
return this._influence.current;
},
/** Sets the interpolation influence */
set: function (value) {
this._influence.current = value;
this._influence.target = value;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "current", {
/** Gets the current track value. */
get: function () {
return this._current;
},
/** Sets the current track value */
set: function (value) {
this._current = value;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "target", {
/** Gets the target track value. */
get: function () {
return this._target;
},
/** Sets the target track value */
set: function (value) {
var containerSize = this.snap.containerSize;
var diff = value - this._target;
this._target = value;
this._influence.target += containerSize ? diff / containerSize : 0;
this._influence.target = (0, math_1.clamp)(this._influence.target, -1, 1);
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "canLoop", {
/** Detect if can loop */
get: function () {
var snap = this.snap;
return snap.props.loop && snap.slides.length > 1;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "loopedCurrent", {
/** Get looped current value */
get: function () {
return this.loopCoord(this.current);
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "offset", {
/** Get track offset */
get: function () {
var snap = this.snap;
return snap.props.centered
? snap.containerSize / 2 - snap.firstSlideSize / 2
: 0;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "loopCount", {
/** Get loop count */
get: function () {
return Math.floor(this.current / this.max);
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "isTransitioning", {
/** If transition in progress */
get: function () {
return !!this._timeline;
},
enumerable: false,
configurable: true
});
/** Set a value to current & target value instantly */
SnapTrack.prototype.set = function (value) {
this.current = value;
this.target = value;
this._influence.current = 0;
this._influence.target = 0;
};
/** Loop a coordinate if can loop */
SnapTrack.prototype.loopCoord = function (coord) {
return this.canLoop ? (0, math_1.loop)(coord, this.min, this.max) : coord;
};
Object.defineProperty(SnapTrack.prototype, "min", {
/** Get minimum track value */
get: function () {
var snap = this.snap;
if (this.canLoop || snap.isEmpty) {
return 0;
}
if (snap.props.centered) {
var firstSlide = snap.slides[0];
if (firstSlide.size > snap.containerSize) {
return snap.containerSize / 2 - firstSlide.size / 2;
}
}
return 0;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "max", {
/** Get maximum track value */
get: function () {
var _a = this.snap, containerSize = _a.containerSize, slides = _a.slides, isEmpty = _a.isEmpty, props = _a.props;
var canLoop = this.canLoop;
if (isEmpty) {
return 0;
}
var firstSlide = slides[0];
var lastSlide = slides[slides.length - 1];
var lastCoordWithSlide = lastSlide.staticCoord + lastSlide.size;
var max = canLoop
? lastCoordWithSlide + (0, utils_1.toPixels)(props.gap)
: lastCoordWithSlide - containerSize;
if (canLoop) {
return max;
}
if (props.centered) {
max += containerSize / 2 - firstSlide.size / 2;
if (lastSlide.size < containerSize) {
max += containerSize / 2 - lastSlide.size / 2;
}
}
if (!props.centered) {
max = Math.max(max, 0);
}
return max;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "progress", {
/** Get track progress. From 0 to 1 if not loop. From -Infinity to Infinity if loop */
get: function () {
return this.current / this.max;
},
enumerable: false,
configurable: true
});
/** Awake requestAnimationFrame */
SnapTrack.prototype.awake = function () {
this._raf.play();
};
/** Iterate track target value */
SnapTrack.prototype.iterateTarget = function (delta) {
this.target += delta;
this.awake();
};
/** Set track target value */
SnapTrack.prototype.setTarget = function (value) {
this.target = value;
this.awake();
};
/** Clamp target value between min and max values */
SnapTrack.prototype.clampTarget = function () {
if (!this.canLoop) {
this.target = (0, math_1.clamp)(this.target, this.min, this.max);
}
this.awake();
};
Object.defineProperty(SnapTrack.prototype, "isStart", {
/** If the start has been reached */
get: function () {
if (this.snap.props.loop) {
return false;
}
return Math.floor(this.target) <= Math.floor(this.min);
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "isEnd", {
/** If the end has been reached */
get: function () {
if (this.snap.props.loop) {
return false;
}
return Math.floor(this.target) >= Math.floor(this.max);
},
enumerable: false,
configurable: true
});
/** Handle RAF update, interpolate track values */
SnapTrack.prototype._handleRaf = function () {
var snap = this.snap;
if (snap.isTransitioning) {
return;
}
// Interpolate track value
var ease = this._raf.lerpFactor(snap.props.lerp);
this.lerp(ease);
// Stop raf if target reached
if (this.isInterpolated) {
this._raf.pause();
}
// Render the scene
snap.render(this._raf.duration);
};
/** Interpolate the current track value */
SnapTrack.prototype.lerp = function (initialFactor) {
var _a = this, snap = _a.snap, min = _a.min, max = _a.max;
var target = this.target;
var lerpFactor = initialFactor;
var influence = this._influence;
// Edge space & resistance
if (!snap.props.loop) {
var containerSize = snap.containerSize;
var edgeSpace = (1 - snap.props.edgeFriction) * containerSize;
if (target < min) {
var edgeProgress = 1 - (0, math_1.scoped)(target, -containerSize, min);
target = min - edgeProgress * edgeSpace;
}
else if (target > max) {
var edgeProgress = (0, math_1.scoped)(target, max, max + containerSize);
target = max + edgeProgress * edgeSpace;
}
target = (0, math_1.clamp)(target, min - edgeSpace, max + edgeSpace);
}
// Interpolate current value
var rest = Math.abs(this.current - target);
var fastThreshold = 3;
if (rest < fastThreshold) {
var fastProgress = 1 - rest / fastThreshold;
var additionalFactor = (1 - lerpFactor) / 15;
lerpFactor += additionalFactor * fastProgress;
}
this.current = (0, math_1.lerp)(this.current, target, lerpFactor, props_1.LERP_APPROXIMATION);
// Interpolate influence
influence.target = (0, math_1.lerp)(influence.target, 0, lerpFactor, props_1.LERP_APPROXIMATION);
influence.current = (0, math_1.lerp)(influence.current, influence.target, lerpFactor, props_1.LERP_APPROXIMATION);
};
/** Cancel sticky behavior */
SnapTrack.prototype.cancelTransition = function () {
var _a;
(_a = this._timeline) === null || _a === void 0 ? void 0 : _a.destroy();
this._timeline = undefined;
};
/** Go to a definite coordinate */
SnapTrack.prototype.toCoord = function (coordinate, options) {
var _this = this;
var _a, _b;
var snap = this.snap;
var props = snap.props, callbacks = snap.callbacks;
if (snap.isEmpty || snap.isDestroyed) {
return false;
}
this.cancelTransition();
var start = this.current;
var end = coordinate;
var diff = Math.abs(end - start);
var durationProp = (_a = options === null || options === void 0 ? void 0 : options.duration) !== null && _a !== void 0 ? _a : snap.props.duration;
var duration = (0, isNumber_1.isNumber)(durationProp) ? durationProp : durationProp(diff);
if (diff === 0) {
duration = 0;
}
var easing = (_b = options === null || options === void 0 ? void 0 : options.easing) !== null && _b !== void 0 ? _b : props.easing;
var tm = new Timeline_1.Timeline({ duration: duration, easing: easing });
this._timeline = tm;
tm.on('start', function () {
var _a;
callbacks.emit('timelineStart', undefined);
(_a = options === null || options === void 0 ? void 0 : options.onStart) === null || _a === void 0 ? void 0 : _a.call(options);
});
tm.on('update', function (data) {
var _a;
_this.current = (0, math_1.lerp)(start, end, data.eased);
_this.target = _this.current;
_this.influence *= 1 - data.progress;
if (data.progress === 1) {
snap.$_targetIndex = undefined;
_this._timeline = undefined;
}
snap.render();
callbacks.emit('timelineUpdate', data);
(_a = options === null || options === void 0 ? void 0 : options.onUpdate) === null || _a === void 0 ? void 0 : _a.call(options, data);
});
tm.on('end', function () {
var _a;
tm.destroy();
callbacks.emit('timelineEnd', undefined);
(_a = options === null || options === void 0 ? void 0 : options.onEnd) === null || _a === void 0 ? void 0 : _a.call(options);
});
tm.on('destroy', function () {
snap.$_targetIndex = undefined;
});
tm.play();
return true;
};
return SnapTrack;
}(SnapLogic_1.SnapLogic));
exports.SnapTrack = SnapTrack;
//# sourceMappingURL=index.js.map