@minto-ai/type-writer
Version:
流式打字机效果组件,提供逐字符显示文本的打字机效果
163 lines (162 loc) • 4.21 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
var TypeWriterStatus = /* @__PURE__ */ ((TypeWriterStatus2) => {
TypeWriterStatus2["PENDING"] = "pending";
TypeWriterStatus2["EXECUTING"] = "executing";
TypeWriterStatus2["COMPLETED"] = "completed";
return TypeWriterStatus2;
})(TypeWriterStatus || {});
class EventBus {
constructor() {
__publicField(this, "listeners", /* @__PURE__ */ new Map());
}
on(eventName, callback) {
const callbacks = this.listeners.get(eventName);
if (callbacks) {
callbacks.push(callback);
} else {
this.listeners.set(eventName, [callback]);
}
}
emit(eventName, data) {
const callbacks = this.listeners.get(eventName);
if (callbacks) {
callbacks.forEach((callback) => {
callback(data);
});
}
}
clear() {
this.listeners.clear();
}
}
let eventBusInstance = null;
function createEventBus() {
if (!eventBusInstance) {
eventBusInstance = new EventBus();
}
return eventBusInstance;
}
const defaultOptions = {
speed: 100
};
class TypeWriter {
constructor(options) {
__publicField(this, "options");
__publicField(this, "status");
__publicField(this, "wordQueue");
__publicField(this, "timer");
__publicField(this, "outputText");
__publicField(this, "isSendComplete");
__publicField(this, "generator");
__publicField(this, "$bus", createEventBus());
this.options = {
...defaultOptions,
...options
};
this.status = TypeWriterStatus.PENDING;
this.wordQueue = [];
this.outputText = "";
this.timer = null;
this.isSendComplete = false;
this.generator = this.createTextGenerator();
}
*createTextGenerator() {
while (true) {
if (this.isSendComplete) {
return;
}
if (this.wordQueue.length === 0) {
yield;
continue;
}
const word = this.wordQueue.shift();
yield word;
}
}
/**
* 发送文本
* @param text 要发送的文本
* @returns 打字机实例
*/
send(text) {
if (this.isSendComplete || this.status === TypeWriterStatus.COMPLETED) {
return this;
}
if ([void 0, null, ""].includes(text)) {
return this;
}
this.wordQueue.push(...text.split(""));
if (this.status === TypeWriterStatus.PENDING) {
this.status = TypeWriterStatus.EXECUTING;
this.execute();
}
return this;
}
/**
* 手动结束打字机
*/
end() {
this.isSendComplete = true;
}
/**
* 手动销毁打字机
*/
finish() {
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
this.wordQueue = [];
this.generator = null;
this.status = TypeWriterStatus.COMPLETED;
this.emit("complete");
this.$bus.clear();
}
execute() {
const result = this.generator.next();
if (result.done) {
this.generator = null;
this.status = TypeWriterStatus.COMPLETED;
this.emit("complete");
this.$bus.clear();
return;
}
if (result.value) {
this.outputText += result.value;
this.emit("change", this.outputText);
}
this.timer = setTimeout(() => {
this.execute();
}, this.options.speed);
}
/**
* 获取当前输出的文本
* @returns 当前输出的文本
*/
getText() {
return this.outputText;
}
emit(eventName, data) {
this.$bus.emit(eventName, data);
}
/**
* 监听事件
* @param eventName 事件名称,支持以下事件:
* - 'change': 文本变化事件,当有新字符输出时触发,回调参数为当前完整文本
* - 'complete': 完成事件,当打字任务完成时触发,无回调参数
* @param callback 回调函数
* @returns 打字机实例
*/
on(eventName, callback) {
this.$bus.on(eventName, callback);
return this;
}
}
function createTypeWriter(options) {
return new TypeWriter(options);
}
export {
createTypeWriter
};