mstf-kit
Version:
一个现代化的 JavaScript/TypeScript 工具库,提供了丰富的常用工具函数
329 lines (328 loc) • 10.5 kB
JavaScript
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
};