maz-ui
Version:
A standalone components library for Vue.Js 3 & Nuxt.Js 3
78 lines (77 loc) • 3.4 kB
JavaScript
import { defineComponent, ref, onMounted, onBeforeUnmount, watch, createElementBlock, openBlock, createElementVNode, renderSlot, createTextVNode, toDisplayString } from "vue";
import { i as isClient } from "../chunks/isClient.WI4oSt66.js";
import { _ as _export_sfc } from "../chunks/_plugin-vue_export-helper.B--vMWp3.js";
import '../assets/MazAnimatedCounter.LK7oyUrl.css';const _hoisted_1 = { class: "maz-sr-only" }, _sfc_main = /* @__PURE__ */ defineComponent({
__name: "MazAnimatedCounter",
props: {
count: {},
duration: { default: 1e3 },
prefix: { default: void 0 },
suffix: { default: void 0 },
delay: { default: 100 },
once: { type: Boolean, default: !0 }
},
setup(__props) {
const props = __props, currentCount = ref(0), elementRef = ref(null);
function getRequestAnimationFrame() {
return !isClient() || !globalThis.requestAnimationFrame ? (callback) => (setTimeout(callback, 1e3 / 60), 0) : globalThis.requestAnimationFrame.bind(globalThis);
}
function animate(start, end, duration, delay) {
const requestAnim = getRequestAnimationFrame();
if (!isClient()) {
currentCount.value = end;
return;
}
currentCount.value = start, setTimeout(() => {
const startTime = performance.now(), updateCount = (currentTime = performance.now()) => {
const elapsed = currentTime - startTime, progress = Math.min(elapsed / duration, 1), easeOutQuad = (t) => t * (2 - t);
currentCount.value = Math.round(
start + (end - start) * easeOutQuad(progress)
), progress < 1 && requestAnim(updateCount);
};
requestAnim(updateCount);
}, delay);
}
function startAnimation(start, end) {
animate(start, end, props.duration, props.delay);
}
let observer = null;
return onMounted(() => {
props.once || (observer = new IntersectionObserver(([entry]) => {
entry.isIntersecting && (startAnimation(0, props.count), props.once && observer?.unobserve(entry.target));
}), elementRef.value && observer.observe(elementRef.value));
}), onBeforeUnmount(() => observer?.disconnect()), watch(
() => props.count,
(newCount, oldCount) => {
if (newCount === oldCount)
return;
startAnimation(oldCount ?? 0, newCount);
},
{ immediate: !0 }
), (_ctx, _cache) => (openBlock(), createElementBlock("span", {
ref_key: "elementRef",
ref: elementRef,
class: "m-animated-counter m-reset-css"
}, [
createElementVNode("span", _hoisted_1, [
renderSlot(_ctx.$slots, "prefix", {}, () => [
createTextVNode(toDisplayString(__props.prefix), 1)
], !0),
createTextVNode(toDisplayString(__props.count), 1),
renderSlot(_ctx.$slots, "suffix", {}, () => [
createTextVNode(toDisplayString(__props.suffix), 1)
], !0)
]),
renderSlot(_ctx.$slots, "prefix", {}, () => [
createTextVNode(toDisplayString(__props.prefix), 1)
], !0),
createTextVNode(toDisplayString(currentCount.value), 1),
renderSlot(_ctx.$slots, "suffix", {}, () => [
createTextVNode(toDisplayString(__props.suffix), 1)
], !0)
], 512));
}
}), MazAnimatedCounter = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-91a33c54"]]);
export {
MazAnimatedCounter as default
};