motion
Version:
The Motion library for the web
132 lines (127 loc) • 4.44 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var defaults = require('../dom/utils/defaults.cjs.js');
var easing = require('../dom/utils/easing.cjs.js');
var getFunction = require('./easing/get-function.cjs.js');
var interpolate = require('./utils/interpolate.cjs.js');
class Animation {
constructor(output, keyframes,
// TODO Merge in defaults
{ easing: easing$1 = defaults.defaults.easing, duration = defaults.defaults.duration, delay = defaults.defaults.delay, endDelay = defaults.defaults.endDelay, offset, repeat = defaults.defaults.repeat, direction = "normal", }) {
this.startTime = 0;
this.rate = 1;
this.t = 0;
this.cancelT = 0;
this.playState = "idle";
this.finished = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
const totalDuration = duration * (repeat + 1);
const interpolate$1 = interpolate.slowInterpolateNumbers(keyframes, offset, easing.isEasingList(easing$1)
? easing$1.map(getFunction.getEasingFunction)
: getFunction.getEasingFunction(easing$1));
this.tick = (timestamp) => {
if (this.playState === "finished") {
const latest = interpolate$1(1);
output(latest);
this.resolve(latest);
return;
}
if (this.pauseTime) {
timestamp = this.pauseTime;
}
let t = (timestamp - this.startTime) * this.rate;
this.t = t;
// Convert to seconds
t /= 1000;
// Rebase on delay
t = Math.max(t - delay, 0);
const progress = t / duration;
// TODO progress += iterationStart
let currentIteration = Math.floor(progress);
let iterationProgress = progress % 1.0;
if (!iterationProgress && progress >= 1) {
iterationProgress = 1;
}
if (iterationProgress === 1) {
currentIteration--;
}
// Reverse progress
const iterationIsOdd = currentIteration % 2;
if (direction === "reverse" ||
(direction === "alternate" && iterationIsOdd) ||
(direction === "alternate-reverse" && !iterationIsOdd)) {
iterationProgress = 1 - iterationProgress;
}
const interpolationIsFinished = t >= totalDuration;
const interpolationProgress = interpolationIsFinished
? 1
: Math.min(iterationProgress, 1);
const latest = interpolate$1(interpolationProgress);
output(latest);
const isFinished = t >= totalDuration + endDelay;
if (isFinished) {
this.playState = "finished";
this.resolve(latest);
}
else if (this.playState !== "idle") {
requestAnimationFrame(this.tick);
}
};
this.play();
}
play() {
const now = performance.now();
this.playState = "running";
if (this.pauseTime) {
this.startTime = now - (this.pauseTime - this.startTime);
}
else if (!this.startTime) {
this.startTime = now;
}
this.pauseTime = undefined;
requestAnimationFrame(this.tick);
}
pause() {
this.playState = "paused";
this.pauseTime = performance.now();
}
finish() {
this.playState = "finished";
this.tick(0);
}
cancel() {
this.playState = "idle";
this.tick(this.cancelT);
this.reject(false);
}
reverse() {
this.rate *= -1;
}
commitStyles() {
this.cancelT = this.t;
}
get currentTime() {
return this.t;
}
set currentTime(t) {
if (this.pauseTime || this.rate === 0) {
this.pauseTime = t;
}
else {
this.startTime = performance.now() - t / this.rate;
}
}
get playbackRate() {
return this.rate;
}
set playbackRate(rate) {
this.rate = rate;
}
}
function animateNumber(output, keyframes = [0, 1], options = {}) {
return new Animation(output, keyframes, options);
}
exports.Animation = Animation;
exports.animateNumber = animateNumber;