vevet
Version:
Vevet is a JavaScript library for creative development that simplifies crafting rich interactions like split text animations, carousels, marquees, preloading, and more.
362 lines • 13.6 kB
JavaScript
"use strict";
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 onlyFinite_1 = require("../../../internal/onlyFinite");
var utils_1 = require("../../../utils");
var math_1 = require("../../../utils/math");
var props_1 = require("../props");
var SnapTrack = /** @class */ (function () {
function SnapTrack(props, _slides, ctx) {
var _this = this;
this.props = props;
this._slides = _slides;
this.ctx = ctx;
/** Interpolation impulse */
this._impulse = { current: 0, target: 0 };
/** The current track value */
this._current = 0;
/** The target track value */
this._target = 0;
/** Whether the track is destroyed */
this._isDestroyed = false;
// Create the animation frame
this._raf = new Raf_1.Raf();
this._raf.on('frame', function () { return _this._handleRaf(); });
this._raf.on('play', function () { var _a; return (_a = ctx.onRafPlay) === null || _a === void 0 ? void 0 : _a.call(ctx); });
this._raf.on('pause', function () { var _a; return (_a = ctx.onRafPause) === null || _a === void 0 ? void 0 : _a.call(ctx); });
}
Object.defineProperty(SnapTrack.prototype, "slides", {
get: function () {
return this._slides();
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "targetIndex", {
/** Gets the target slide index */
get: function () {
return this._targetIndex;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "impulse", {
/** Gets the interpolation impulse */
get: function () {
return this._impulse.current;
},
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.ctx.containerSize();
var diff = value - this._target;
this._target = value;
this._impulse.target += containerSize
? (0, onlyFinite_1.onlyFinite)(diff / containerSize)
: 0;
this._impulse.target = (0, math_1.clamp)(this._impulse.target, -1, 1);
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "canLoop", {
/** Detect if can loop */
get: function () {
var _a = this, props = _a.props, slides = _a.slides;
return props.loop && 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 ctx = this.ctx;
var origin = ctx.origin();
var containerSize = ctx.containerSize();
var firstSlideSize = ctx.firstSlideSize();
if (origin === 'center') {
return containerSize / 2 - firstSlideSize / 2;
}
else if (origin === 'end') {
return containerSize - firstSlideSize;
}
return 0;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "loopCount", {
/** Get loop count */
get: function () {
if (!this.canLoop) {
return 0;
}
return Math.floor((0, onlyFinite_1.onlyFinite)(this.current / this.max));
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "isTransitioning", {
/** If transition in progress */
get: function () {
return !!this._tm;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "min", {
/** Get minimum track value */
get: function () {
var containerSize = this.ctx.containerSize();
var origin = this.ctx.origin();
var firstSlide = this.slides[0];
if (this.canLoop) {
return 0;
}
if (origin === 'center') {
if (firstSlide.size > containerSize) {
return containerSize / 2 - firstSlide.size / 2;
}
}
if (origin === 'end') {
if (firstSlide.size > containerSize) {
return containerSize - firstSlide.size;
}
}
return 0;
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "max", {
/** Get maximum track value */
get: function () {
var containerSize = this.ctx.containerSize();
var origin = this.ctx.origin();
var _a = this, slides = _a.slides, canLoop = _a.canLoop, props = _a.props;
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 (origin === 'center') {
max += containerSize / 2 - firstSlide.size / 2;
if (lastSlide.size < containerSize) {
max += containerSize / 2 - lastSlide.size / 2;
}
}
if (origin === 'end') {
max += containerSize - firstSlide.size;
}
if (origin === 'start') {
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 (0, onlyFinite_1.onlyFinite)(this.current / this.max);
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "isStart", {
/** If the start has been reached */
get: function () {
if (this.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.props.loop) {
return false;
}
return Math.floor(this.target) >= Math.floor(this.max);
},
enumerable: false,
configurable: true
});
Object.defineProperty(SnapTrack.prototype, "isInterpolated", {
/** Whether the track is interpolated */
get: function () {
return this.current === this.target && this._impulse.current === 0;
},
enumerable: false,
configurable: true
});
/** Handle RAF update, interpolate track values */
SnapTrack.prototype._handleRaf = function () {
var _a = this, isTransitioning = _a.isTransitioning, props = _a.props, raf = _a._raf;
if (isTransitioning) {
return;
}
// Interpolate track value
var ease = raf.lerpFactor(props.lerp);
this._lerp(ease);
// Stop raf if target reached
if (this.isInterpolated) {
raf.pause();
}
// Render the scene
this.ctx.onRender(raf.duration);
};
/** Awake requestAnimationFrame */
SnapTrack.prototype.awake = function () {
this._raf.play();
};
/** Set track target value */
SnapTrack.prototype.updateTarget = 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();
};
/** Set a value to current & target value instantly */
SnapTrack.prototype.set = function (value) {
this.current = value;
this.target = value;
this._impulse.current = 0;
this._impulse.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;
};
/** Interpolate the current track value */
SnapTrack.prototype._lerp = function (initialFactor) {
var _a = this, target = _a.target, impulse = _a._impulse;
var lerpFactor = initialFactor;
// 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 impulse
impulse.target = (0, math_1.lerp)(impulse.target, 0, lerpFactor, props_1.LERP_APPROXIMATION);
impulse.current = (0, math_1.lerp)(impulse.current, impulse.target, lerpFactor, props_1.LERP_APPROXIMATION);
};
/** Go to a definite coordinate */
SnapTrack.prototype.toCoord = function (coordinate, options) {
var _this = this;
var _a, _b;
if (this._isDestroyed) {
return false;
}
var _c = this, props = _c.props, ctx = _c.ctx;
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 : 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._tm = tm;
tm.on('start', function () {
var _a;
ctx.onTimelineStart();
(_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._impulse.current = _this._impulse.current * (1 - data.progress);
_this._impulse.target = _this._impulse.current;
if (data.progress === 1) {
_this.setTargetIndex(undefined);
_this._tm = undefined;
}
ctx.onTimelineUpdate(data);
ctx.onRender();
(_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();
ctx.onTimelineEnd();
(_a = options === null || options === void 0 ? void 0 : options.onEnd) === null || _a === void 0 ? void 0 : _a.call(options);
});
tm.on('destroy', function () {
_this.setTargetIndex(undefined);
});
tm.play();
return true;
};
/** Set target index */
SnapTrack.prototype.setTargetIndex = function (value) {
this._targetIndex = value;
};
/** Cancel sticky behavior */
SnapTrack.prototype.cancelTransition = function () {
var _a;
(_a = this._tm) === null || _a === void 0 ? void 0 : _a.destroy();
this._tm = undefined;
};
/** Destroy the instance */
SnapTrack.prototype.destroy = function () {
this._isDestroyed = true;
this._raf.destroy();
this.cancelTransition();
};
return SnapTrack;
}());
exports.SnapTrack = SnapTrack;
//# sourceMappingURL=index.js.map