@stimulus-library/controllers
Version:
A library of useful controllers for Stimulus
79 lines (78 loc) • 2.54 kB
JavaScript
import { BaseController, EasingFunctions } from "@stimulus-library/utilities";
import { useIntersection } from "@stimulus-library/mixins";
export class TweenNumberController extends BaseController {
get start() {
if (this.hasStartValue) {
return this.startValue;
}
else {
throw new Error("Required value `start` is missing");
}
}
get end() {
if (this.hasEndValue) {
return this.endValue;
}
else {
throw new Error("Required value `end` is missing");
}
}
get durationMs() {
if (this.hasDurationValue) {
return this.durationValue;
}
else {
throw new Error("Required value `duration` is missing");
}
}
get easingFunction() {
const str = this.hasEasingValue ? this.easingValue : null;
const fallback = EasingFunctions.linear;
if (str == null) {
return fallback;
}
return EasingFunctions[str] || fallback;
}
connect() {
const { observer, observe, unobserve, teardown, } = useIntersection(this, this.el, this.appear);
this.observer = observer;
this.observe = observe;
this.unobserve = unobserve;
this.teardownObserver = teardown;
this.formatter = new Intl.NumberFormat(Intl.NumberFormat().resolvedOptions().locale, this.formattingValue);
}
appear(_entry) {
this.tween();
}
tween() {
let startTimestamp = null;
const self = this;
const step = (timestamp) => {
var _a, _b;
if (!startTimestamp) {
startTimestamp = timestamp;
}
const elapsed = timestamp - startTimestamp;
const progress = Math.min(elapsed / this.durationMs, 1);
this.element.innerHTML = this.formatter.format(Math.floor(this.easingFunction(progress) * (this.end - this.start) + this.start));
if (progress < 1) {
requestAnimationFrame(step);
}
else {
(_a = self.unobserve) === null || _a === void 0 ? void 0 : _a.call(self);
(_b = self.teardownObserver) === null || _b === void 0 ? void 0 : _b.call(self);
}
};
requestAnimationFrame(step);
}
}
TweenNumberController.values = {
start: Number,
end: Number,
duration: Number,
easing: String,
formatting: {
type: Object,
default: {},
},
};