@asasugar-use/vue3-typewriter
Version:
Vue3 Component for typewriter effects.
86 lines (85 loc) • 2.73 kB
JavaScript
import { defineComponent, useCssVars, useAttrs, ref, computed, watch, onUnmounted, openBlock, createElementBlock, createElementVNode, mergeProps, unref, toDisplayString, createCommentVNode } from "vue";
const _hoisted_1 = { key: 0 };
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "vue3-typewriter",
props: {
text: {},
typingSpeed: { default: 100 },
cursorColor: { default: "red" },
cursorShow: { type: Boolean, default: true }
},
emits: ["completed"],
setup(__props, { emit: __emit }) {
useCssVars((_ctx) => ({
"3338934b": props.cursorColor
}));
const props = __props;
const emit = __emit;
const attrs = useAttrs();
const displayedText = ref("");
const isFinished = ref(false);
const isCursorHidden = computed(() => !props.cursorShow || isFinished.value);
let currentIndex = 0;
let lastTime = 0;
let animationFrameId;
const typeWriterEffect = (time) => {
if (currentIndex < props.text.length) {
if (!lastTime) lastTime = time;
const timeDifference = time - lastTime;
if (timeDifference > props.typingSpeed) {
displayedText.value += props.text.charAt(currentIndex);
currentIndex++;
lastTime = time;
}
animationFrameId = requestAnimationFrame(typeWriterEffect);
} else {
isFinished.value = true;
emit("completed");
}
};
watch(
() => props.text,
(newText, oldText) => {
if (newText.length < oldText.length) {
displayedText.value = newText.slice(0, currentIndex);
}
isFinished.value = false;
animationFrameId = requestAnimationFrame(typeWriterEffect);
}
);
onUnmounted(() => {
cancelAnimationFrame(animationFrameId);
});
return (_ctx, _cache) => {
return displayedText.value ? (openBlock(), createElementBlock("div", _hoisted_1, [
createElementVNode("span", mergeProps({ ...unref(attrs) }, {
class: ["text", { "cursor-hidden": isCursorHidden.value }]
}), toDisplayString(displayedText.value), 17)
])) : createCommentVNode("", true);
};
}
});
const _export_sfc = (sfc, props) => {
const target = sfc.__vccOpts || sfc;
for (const [key, val] of props) {
target[key] = val;
}
return target;
};
const Vue3Typewriter = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-4c7ca741"]]);
let installed = false;
function install(app) {
if (installed) return;
installed = true;
app.component("Vue3Typewriter", Vue3Typewriter);
}
const plugin = {
install
};
if (typeof window !== "undefined" && window.Vue) {
window.Vue.use(plugin);
}
export {
Vue3Typewriter as default,
install
};