UNPKG

mstf-kit

Version:

一个现代化的 JavaScript/TypeScript 工具库,提供了丰富的常用工具函数

329 lines (328 loc) 10.5 kB
import { DotLottie } from "@lottiefiles/dotlottie-web"; function isLottieLoaded() { return typeof window !== "undefined" && "DotLottie" in window; } async function getLottieLibrary(options = {}) { const source = options.source || "built-in"; if (isLottieLoaded()) { return window.DotLottie; } switch (source) { // 内置库模式(默认模式) case "built-in": { if (typeof window !== "undefined") { window.DotLottie = DotLottie; } return DotLottie; } // 外部库模式 case "external": { if (!options.externalLib) { throw new Error('External library not provided. Please provide externalLib when using source="external"'); } if (typeof window !== "undefined") { window.DotLottie = options.externalLib; } return options.externalLib; } // CDN加载模式 case "cdn": { return new Promise((resolve, reject) => { const script = document.createElement("script"); script.src = options.cdnURL || "https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-web/+esm"; script.type = "module"; script.async = true; script.onload = () => { const DotLottieClass = window.DotLottie; if (!DotLottieClass) { reject(new Error("Failed to load DotLottie from CDN")); return; } resolve(DotLottieClass); }; script.onerror = () => reject(new Error("Failed to load DotLottie library from CDN")); document.head.appendChild(script); }); } default: throw new Error(`Invalid library source: ${source}`); } } function getDOMElement(container) { if (!container) { return null; } if (typeof container === "string") { return document.querySelector(container); } if (container instanceof HTMLElement) { return container; } if (container && "value" in container && container.value instanceof HTMLElement) { return container.value; } return null; } async function createLottiePlayer(options) { const LottieClass = await getLottieLibrary(options.libOptions); const container = getDOMElement(options.container); if (!container) { throw new Error("Lottie container not found or invalid"); } const defaultOptions = { renderer: "svg", loop: false, autoplay: false, speed: 1, direction: 1, quality: 1, libOptions: { source: "built-in" } }; const config = { ...defaultOptions, ...options }; let canvas; const containerIsCanvas = container instanceof HTMLCanvasElement; if (containerIsCanvas) { canvas = container; } else { container.innerHTML = ""; canvas = document.createElement("canvas"); canvas.style.width = "100%"; canvas.style.height = "100%"; container.appendChild(canvas); } let state = "loading"; let animInstance = null; let pendingSource = null; let dotLottieInstance = null; const player = { async load(source) { try { state = "loading"; if (dotLottieInstance) { dotLottieInstance.destroy(); dotLottieInstance = null; } pendingSource = source; const animParams = { canvas, autoplay: config.autoplay, loop: config.loop === true ? true : config.loop === false ? false : config.loop, speed: config.speed }; if (typeof source === "string") { if (source.startsWith("http") || source.startsWith("./") || source.startsWith("/") || source.endsWith(".json") || source.endsWith(".lottie")) { animParams.src = source; } else if (source.startsWith("{")) { try { animParams.data = JSON.parse(source); } catch (e) { throw new Error("Invalid Lottie JSON string"); } } else { throw new Error("Invalid Lottie source"); } } else { animParams.data = source; } dotLottieInstance = new LottieClass(animParams); animInstance = dotLottieInstance; if (config.onComplete) { dotLottieInstance.addEventListener("complete", config.onComplete); } if (config.onLoopComplete) { dotLottieInstance.addEventListener("loopComplete", config.onLoopComplete); } if (config.onFrame) { dotLottieInstance.addEventListener("frame", (e) => { var _a, _b; (_b = config.onFrame) == null ? void 0 : _b.call(config, ((_a = e.detail) == null ? void 0 : _a.frame) || 0); }); } if (config.onError) { dotLottieInstance.addEventListener("error", (e) => { var _a, _b; (_b = config.onError) == null ? void 0 : _b.call(config, ((_a = e.detail) == null ? void 0 : _a.error) || new Error("Unknown error")); }); } if (config.onLoad) { dotLottieInstance.addEventListener("ready", config.onLoad); } if (config.onPlay) { dotLottieInstance.addEventListener("play", config.onPlay); } if (config.onPause) { dotLottieInstance.addEventListener("pause", config.onPause); } if (config.onStop) { dotLottieInstance.addEventListener("stop", config.onStop); } if (config.onDestroy) { dotLottieInstance.addEventListener("destroy", config.onDestroy); } if (config.direction === -1) { dotLottieInstance.setDirection(-1); } if (config.initialSegment) { dotLottieInstance.setSegments(config.initialSegment[0], config.initialSegment[1]); } await new Promise((resolve) => { dotLottieInstance.addEventListener("ready", () => { state = config.autoplay ? "playing" : "paused"; resolve(); }, { once: true }); dotLottieInstance.addEventListener("error", (e) => { state = "error"; resolve(); }, { once: true }); }); } catch (error) { state = "error"; if (config.onError) config.onError(error instanceof Error ? error : new Error("Failed to load animation")); throw error; } }, play() { if (!dotLottieInstance) return; dotLottieInstance.play(); state = "playing"; }, pause() { if (!dotLottieInstance) return; dotLottieInstance.pause(); state = "paused"; }, stop() { if (!dotLottieInstance) return; dotLottieInstance.stop(); state = "stopped"; }, goToFrame(frame) { if (!dotLottieInstance) return; dotLottieInstance.seek(`${Math.round(frame)}/${this.getTotalFrames()}`); }, goToAndPlay(frame) { if (!dotLottieInstance) return; this.goToFrame(frame); this.play(); }, goToAndStop(frame) { if (!dotLottieInstance) return; this.goToFrame(frame); this.pause(); }, setSpeed(speed) { if (!dotLottieInstance) return; dotLottieInstance.setSpeed(speed); }, setDirection(direction) { if (!dotLottieInstance) return; dotLottieInstance.setDirection(direction); }, setLoop(loop) { if (!dotLottieInstance) return; if (typeof loop === "boolean") { dotLottieInstance.setLooping(loop); } else { let loopCount = 0; const maxLoops = loop; dotLottieInstance.removeEventListener("loopComplete"); if (loop > 0) { dotLottieInstance.setLooping(true); dotLottieInstance.addEventListener("loopComplete", () => { loopCount++; if (loopCount >= maxLoops) { dotLottieInstance.setLooping(false); dotLottieInstance.pause(); state = "paused"; } }); } else { dotLottieInstance.setLooping(false); } } }, getCurrentFrame() { var _a; if (!dotLottieInstance) return 0; return (_a = dotLottieInstance.currentFrame) != null ? _a : 0; }, getTotalFrames() { var _a; if (!dotLottieInstance) return 0; return (_a = dotLottieInstance.totalFrames) != null ? _a : 0; }, getDuration() { var _a; if (!dotLottieInstance) return 0; return ((_a = dotLottieInstance.duration) != null ? _a : 0) * 1e3; }, getState() { return state; }, isPlaying() { if (!dotLottieInstance) return false; return dotLottieInstance.isPlaying() || state === "playing"; }, setSegment(startFrame, endFrame) { if (!dotLottieInstance) return; dotLottieInstance.setSegments(startFrame, endFrame); }, setQuality(quality) { if (!dotLottieInstance) return; }, getAnimationInstance() { return dotLottieInstance; }, resize() { if (!dotLottieInstance) return; dotLottieInstance.resize(); }, destroy() { if (!dotLottieInstance) return; dotLottieInstance.removeEventListener("complete"); dotLottieInstance.removeEventListener("loopComplete"); dotLottieInstance.removeEventListener("frame"); dotLottieInstance.removeEventListener("error"); dotLottieInstance.removeEventListener("ready"); dotLottieInstance.removeEventListener("play"); dotLottieInstance.removeEventListener("pause"); dotLottieInstance.removeEventListener("stop"); dotLottieInstance.removeEventListener("destroy"); dotLottieInstance.destroy(); dotLottieInstance = null; animInstance = null; state = "destroyed"; } }; return player; } async function playLottie(url, container, options = {}) { const player = await createLottiePlayer({ container, autoplay: options.autoplay !== void 0 ? options.autoplay : true, loop: options.loop !== void 0 ? options.loop : true, renderer: options.renderer || "svg", speed: options.speed || 1, direction: options.direction || 1, quality: options.quality || 1, initialSegment: options.initialSegment, libOptions: options.libOptions, onLoad: options.onLoad, onComplete: options.onComplete, onLoopComplete: options.onLoopComplete, onFrame: options.onFrame, onPlay: options.onPlay, onPause: options.onPause, onStop: options.onStop, onError: options.onError, onDestroy: options.onDestroy }); await player.load(url); return player; } export { createLottiePlayer, playLottie };