初始化奇妙小屏幕控制器项目
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
export const MIN_FRAME_DURATION_MS = 50;
|
||||
export const MAX_FRAME_DURATION_MS = 604800000;
|
||||
|
||||
export function effectiveFrameName(animationName, frame, position = frame?.position) {
|
||||
const customName = typeof frame?.name === "string" ? frame.name.trim() : "";
|
||||
if (customName) return customName;
|
||||
return `${String(animationName || "动图").trim() || "动图"}-第${position}帧`;
|
||||
}
|
||||
|
||||
export function animationEditContextName(animationName, frame, position = frame?.position) {
|
||||
const normalizedAnimationName = String(animationName || "动图").trim() || "动图";
|
||||
const customName = typeof frame?.name === "string" ? frame.name.trim() : "";
|
||||
return `${normalizedAnimationName}-${customName || `第${position}帧`}`;
|
||||
}
|
||||
|
||||
export function animationPreviewFrameAtElapsed(frames, elapsedMs) {
|
||||
if (!Array.isArray(frames) || !frames.length) return null;
|
||||
const durations = frames.map((frame) => Number(frame?.duration_ms));
|
||||
if (durations.some((duration) => !Number.isFinite(duration) || duration <= 0)) return null;
|
||||
const totalDurationMs = durations.reduce((total, duration) => total + duration, 0);
|
||||
const normalizedElapsed = Number.isFinite(Number(elapsedMs)) ? Number(elapsedMs) : 0;
|
||||
const cycleElapsedMs = ((normalizedElapsed % totalDurationMs) + totalDurationMs) % totalDurationMs;
|
||||
let boundary = 0;
|
||||
for (let index = 0; index < frames.length; index += 1) {
|
||||
boundary += durations[index];
|
||||
if (cycleElapsedMs < boundary) {
|
||||
return {
|
||||
frame: frames[index],
|
||||
index,
|
||||
remainingMs: boundary - cycleElapsedMs,
|
||||
totalDurationMs,
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function formatFrameDuration(durationMs, unit = "ms") {
|
||||
const duration = Number(durationMs);
|
||||
if (!Number.isInteger(duration)) return "";
|
||||
if (unit === "ms") return String(duration);
|
||||
if (unit !== "s") throw new Error("unknown animation duration unit");
|
||||
return (duration / 1000).toFixed(3).replace(/\.?0+$/, "");
|
||||
}
|
||||
|
||||
export function validateFrameDuration(value, unit = "ms") {
|
||||
const normalized = typeof value === "string" ? value.trim() : String(value ?? "").trim();
|
||||
const millisecondsPattern = /^\d+$/;
|
||||
const secondsPattern = /^\d+(?:\.\d{1,3})?$/;
|
||||
if (!normalized || (unit === "ms" ? !millisecondsPattern.test(normalized) : !secondsPattern.test(normalized))) {
|
||||
return {
|
||||
valid: false,
|
||||
duration: null,
|
||||
error: unit === "ms"
|
||||
? `请输入 ${MIN_FRAME_DURATION_MS}..${MAX_FRAME_DURATION_MS} 之间的整数毫秒值。`
|
||||
: "请输入 0.050..604800 之间、最多三位小数的秒数。",
|
||||
};
|
||||
}
|
||||
const numeric = Number(normalized);
|
||||
const duration = unit === "s" ? numeric * 1000 : numeric;
|
||||
if (!Number.isInteger(duration) || duration < MIN_FRAME_DURATION_MS || duration > MAX_FRAME_DURATION_MS) {
|
||||
return {
|
||||
valid: false,
|
||||
duration: null,
|
||||
error: unit === "ms"
|
||||
? `请输入 ${MIN_FRAME_DURATION_MS}..${MAX_FRAME_DURATION_MS} 之间的整数毫秒值。`
|
||||
: "请输入 0.050..604800 之间、最多三位小数的秒数。",
|
||||
};
|
||||
}
|
||||
return { valid: true, duration, error: "" };
|
||||
}
|
||||
|
||||
export function reorderSelectedFrameIds(frameIds, selectedFrameIds, insertAfterFrameId = null) {
|
||||
if (!Array.isArray(frameIds) || !Array.isArray(selectedFrameIds) || !selectedFrameIds.length) return null;
|
||||
const selected = new Set(selectedFrameIds);
|
||||
if (selected.size !== selectedFrameIds.length || selectedFrameIds.some((id) => !frameIds.includes(id))) return null;
|
||||
if (insertAfterFrameId !== null && (!frameIds.includes(insertAfterFrameId) || selected.has(insertAfterFrameId))) return null;
|
||||
const moving = frameIds.filter((id) => selected.has(id));
|
||||
const remaining = frameIds.filter((id) => !selected.has(id));
|
||||
const insertAt = insertAfterFrameId === null ? 0 : remaining.indexOf(insertAfterFrameId) + 1;
|
||||
return [...remaining.slice(0, insertAt), ...moving, ...remaining.slice(insertAt)];
|
||||
}
|
||||
Reference in New Issue
Block a user