From c28adf9fae599c7d415fac04194af28e6ac1dd8f Mon Sep 17 00:00:00 2001 From: YeomaiPC Date: Sun, 20 Sep 2026 02:31:07 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BC=A9=E7=95=A5=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _locales/de_DE.json | 2 +- _locales/en.json | 2 +- _locales/es_ES.json | 2 +- _locales/ja_JP.json | 2 +- _locales/ko_KR.json | 2 +- _locales/ru_RU.json | 2 +- _locales/zh_CN.json | 2 +- _locales/zh_TW.json | 2 +- js/animated-profiles.js | 15 +++++++++++++++ .../UNIVERSAL_SpineViewer/_locales/de_DE.json | 2 +- release/UNIVERSAL_SpineViewer/_locales/en.json | 2 +- .../UNIVERSAL_SpineViewer/_locales/es_ES.json | 2 +- .../UNIVERSAL_SpineViewer/_locales/ja_JP.json | 2 +- .../UNIVERSAL_SpineViewer/_locales/ko_KR.json | 2 +- .../UNIVERSAL_SpineViewer/_locales/ru_RU.json | 2 +- .../UNIVERSAL_SpineViewer/_locales/zh_CN.json | 2 +- .../UNIVERSAL_SpineViewer/_locales/zh_TW.json | 2 +- .../js/animated-profiles.js | 15 +++++++++++++++ .../UNIVERSAL_SpineViewer/viewer/spine.html | 9 ++++++--- tests/apng-thumbnail.test.js | 18 ++++++++++++++++-- viewer/spine.html | 9 ++++++--- 21 files changed, 74 insertions(+), 24 deletions(-) diff --git a/_locales/de_DE.json b/_locales/de_DE.json index dd7c524..1df5d28 100644 --- a/_locales/de_DE.json +++ b/_locales/de_DE.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "Diese Umgebung kann WebP nicht kodieren. Bitte APNG auswählen.", "animatedCannotFit": "Die Animation kann nicht auf {target} KB reduziert werden (mindestens etwa {actual} KB). Erhöhen Sie das Limit oder verkürzen Sie den Framebereich.", "animatedPickTitle": "Miniaturbild auswählen", - "animatedPickHint": "Alle Ergebnisse behalten eine 400×400-Arbeitsfläche; das Label zeigt Detailauflösung@fps/Qualität/Dateigröße. Wählen Sie eines und drücken Sie Bestätigen, um es zu übernehmen, oder brechen Sie ab, um alle zu verwerfen.", + "animatedPickHint": "Alle Ergebnisse behalten eine {size}-Arbeitsfläche; das Label zeigt Detailauflösung@fps/Qualität/Dateigröße. Wählen Sie eines und drücken Sie Bestätigen, um es zu übernehmen, oder brechen Sie ab, um alle zu verwerfen.", "animatedPickConfirm": "Bestätigen", "animatedPriority": "Priorität", "animatedCanvas": "Ausgabegröße", diff --git a/_locales/en.json b/_locales/en.json index d57c9f2..3c85903 100644 --- a/_locales/en.json +++ b/_locales/en.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "This environment cannot encode WebP. Choose APNG instead.", "animatedCannotFit": "The animation cannot be reduced to {target} KB (minimum about {actual} KB). Increase the limit or shorten the frame range.", "animatedPickTitle": "Pick a thumbnail", - "animatedPickHint": "Every result keeps a 400×400 canvas; the label shows detail resolution@fps/quality/file size. Select one and press Confirm to replace the thumbnail, or cancel to discard them all.", + "animatedPickHint": "Every result keeps a {size} canvas; the label shows detail resolution@fps/quality/file size. Select one and press Confirm to replace the thumbnail, or cancel to discard them all.", "animatedPickConfirm": "Confirm", "animatedPriority": "Priority", "animatedCanvas": "Canvas size", diff --git a/_locales/es_ES.json b/_locales/es_ES.json index ff8234a..e87ec76 100644 --- a/_locales/es_ES.json +++ b/_locales/es_ES.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "Este entorno no puede codificar WebP. Selecciona APNG.", "animatedCannotFit": "No se puede reducir la animación a {target} KB (mínimo aproximado: {actual} KB). Aumenta el límite o acorta el rango.", "animatedPickTitle": "Elige una miniatura", - "animatedPickHint": "Todos los resultados mantienen un lienzo de 400×400; la etiqueta indica la resolución de detalle@fps/calidad/tamaño de archivo. Elige uno y pulsa Confirmar para aplicarlo, o cancela para descartarlos todos.", + "animatedPickHint": "Todos los resultados mantienen un lienzo de {size}; la etiqueta indica la resolución de detalle@fps/calidad/tamaño de archivo. Elige uno y pulsa Confirmar para aplicarlo, o cancela para descartarlos todos.", "animatedPickConfirm": "Confirmar", "animatedPriority": "Prioridad", "animatedCanvas": "Tamaño del lienzo", diff --git a/_locales/ja_JP.json b/_locales/ja_JP.json index 6bae31b..8e57ef7 100644 --- a/_locales/ja_JP.json +++ b/_locales/ja_JP.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "この環境では WebP をエンコードできません。APNG を選択してください。", "animatedCannotFit": "アニメーションを {target} KB まで圧縮できません(最小約 {actual} KB)。上限を増やすかフレーム範囲を短くしてください。", "animatedPickTitle": "サムネイルを選択", - "animatedPickHint": "すべての結果は 400×400 のキャンバスです。ラベルは実際のディテール解像度@fps/品質/ファイルサイズを示します。1つ選んで確認を押すと置き換え、キャンセルですべて破棄します。", + "animatedPickHint": "すべての結果は {size} のキャンバスです。ラベルは実際のディテール解像度@fps/品質/ファイルサイズを示します。1つ選んで確認を押すと置き換え、キャンセルですべて破棄します。", "animatedPickConfirm": "確認", "animatedPriority": "優先度", "animatedCanvas": "出力サイズ", diff --git a/_locales/ko_KR.json b/_locales/ko_KR.json index 98872bc..5d1e060 100644 --- a/_locales/ko_KR.json +++ b/_locales/ko_KR.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "현재 환경에서 WebP를 인코딩할 수 없습니다. APNG를 선택하세요.", "animatedCannotFit": "애니메이션을 {target}KB로 줄일 수 없습니다(최소 약 {actual}KB). 제한을 높이거나 프레임 범위를 줄이세요.", "animatedPickTitle": "썸네일 선택", - "animatedPickHint": "모든 결과의 캔버스는 400×400이며, 라벨은 실제 디테일 해상도@fps/품질/파일 크기입니다. 하나를 선택하고 확인을 누르면 적용되고, 취소하면 모두 버려집니다.", + "animatedPickHint": "모든 결과의 캔버스는 {size}이며, 라벨은 실제 디테일 해상도@fps/품질/파일 크기입니다. 하나를 선택하고 확인을 누르면 적용되고, 취소하면 모두 버려집니다.", "animatedPickConfirm": "확인", "animatedPriority": "우선 순위", "animatedCanvas": "출력 크기", diff --git a/_locales/ru_RU.json b/_locales/ru_RU.json index ff73f7b..d87df6a 100644 --- a/_locales/ru_RU.json +++ b/_locales/ru_RU.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "Эта среда не поддерживает кодирование WebP. Выберите APNG.", "animatedCannotFit": "Анимацию нельзя уменьшить до {target} КБ (минимум около {actual} КБ). Увеличьте лимит или сократите диапазон кадров.", "animatedPickTitle": "Выберите миниатюру", - "animatedPickHint": "У всех результатов холст 400×400; в подписи указаны реальное разрешение детализации@fps/качество/размер файла. Выберите результат и нажмите «Подтвердить», чтобы применить его, или отмените, чтобы всё отбросить.", + "animatedPickHint": "У всех результатов холст {size}; в подписи указаны реальное разрешение детализации@fps/качество/размер файла. Выберите результат и нажмите «Подтвердить», чтобы применить его, или отмените, чтобы всё отбросить.", "animatedPickConfirm": "Подтвердить", "animatedPriority": "Приоритет", "animatedCanvas": "Размер холста", diff --git a/_locales/zh_CN.json b/_locales/zh_CN.json index 45a2284..35531ca 100644 --- a/_locales/zh_CN.json +++ b/_locales/zh_CN.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "当前环境不支持 WebP 编码,请选择 APNG", "animatedCannotFit": "无法在保留动画的前提下压缩到 {target} KB(最小约 {actual} KB),请提高上限或缩短帧范围", "animatedPickTitle": "选择一个缩略图", - "animatedPickHint": "所有结果画布都是 400×400,标签为实际细节分辨率@帧率/质量/文件大小。点选一个结果后按确认替换缩略图,取消则全部放弃。", + "animatedPickHint": "所有结果画布都是 {size},标签为实际细节分辨率@帧率/质量/文件大小。点选一个结果后按确认替换缩略图,取消则全部放弃。", "animatedPickConfirm": "确认", "animatedPriority": "优先级别", "animatedCanvas": "输出尺寸", diff --git a/_locales/zh_TW.json b/_locales/zh_TW.json index ea2ef70..7096ce3 100644 --- a/_locales/zh_TW.json +++ b/_locales/zh_TW.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "目前環境不支援 WebP 編碼,請選擇 APNG", "animatedCannotFit": "無法在保留動畫的情況下壓縮到 {target} KB(最小約 {actual} KB),請提高上限或縮短影格範圍", "animatedPickTitle": "選擇一個縮圖", - "animatedPickHint": "所有結果畫布都是 400×400,標籤為實際細節解析度@影格率/品質/檔案大小。點選一個結果後按確認替換縮圖,取消則全部放棄。", + "animatedPickHint": "所有結果畫布都是 {size},標籤為實際細節解析度@影格率/品質/檔案大小。點選一個結果後按確認替換縮圖,取消則全部放棄。", "animatedPickConfirm": "確認", "animatedPriority": "優先級別", "animatedCanvas": "輸出尺寸", diff --git a/js/animated-profiles.js b/js/animated-profiles.js index 1663494..d4da6ff 100644 --- a/js/animated-profiles.js +++ b/js/animated-profiles.js @@ -42,9 +42,21 @@ const DEFAULT_PRIORITY = 'resolution'; const ANIMATED_OUTPUT_SIZES = [200, 400]; const DEFAULT_OUTPUT_SIZE = 200; +/** + * 「缩略图大小」输入框的默认建议值:每秒动画配 25 KB,夹在 25–100 KB 之间。 + * 只是打开面板时的初始值,用户随时可以手动改成 10–1024 之间的任意数。 + */ +const SIZE_PER_SECOND = 25; +const SIZE_SUGGESTION_RANGE = [25, 100]; + // 相邻锚点之间插多少个采样点。数值越大,越容易压在目标体积附近,但粗估阶段耗时略增。 const PATH_STEPS_PER_SEGMENT = 6; +function suggestSize(seconds) { + const [min, max] = SIZE_SUGGESTION_RANGE; + return Math.max(min, Math.min(max, Math.round((Number(seconds) || 0) * SIZE_PER_SECOND))); +} + function animatedProfiles(priority, outputSize) { const limit = outputSize || DEFAULT_OUTPUT_SIZE; const plan = ANIMATED_PRIORITIES[priority] || ANIMATED_PRIORITIES[DEFAULT_PRIORITY]; @@ -86,7 +98,10 @@ module.exports = { DEFAULT_PRIORITY, ANIMATED_OUTPUT_SIZES, DEFAULT_OUTPUT_SIZE, + SIZE_PER_SECOND, + SIZE_SUGGESTION_RANGE, PATH_STEPS_PER_SEGMENT, animatedProfiles, expandAnimatedPath, + suggestSize, }; diff --git a/release/UNIVERSAL_SpineViewer/_locales/de_DE.json b/release/UNIVERSAL_SpineViewer/_locales/de_DE.json index dd7c524..1df5d28 100644 --- a/release/UNIVERSAL_SpineViewer/_locales/de_DE.json +++ b/release/UNIVERSAL_SpineViewer/_locales/de_DE.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "Diese Umgebung kann WebP nicht kodieren. Bitte APNG auswählen.", "animatedCannotFit": "Die Animation kann nicht auf {target} KB reduziert werden (mindestens etwa {actual} KB). Erhöhen Sie das Limit oder verkürzen Sie den Framebereich.", "animatedPickTitle": "Miniaturbild auswählen", - "animatedPickHint": "Alle Ergebnisse behalten eine 400×400-Arbeitsfläche; das Label zeigt Detailauflösung@fps/Qualität/Dateigröße. Wählen Sie eines und drücken Sie Bestätigen, um es zu übernehmen, oder brechen Sie ab, um alle zu verwerfen.", + "animatedPickHint": "Alle Ergebnisse behalten eine {size}-Arbeitsfläche; das Label zeigt Detailauflösung@fps/Qualität/Dateigröße. Wählen Sie eines und drücken Sie Bestätigen, um es zu übernehmen, oder brechen Sie ab, um alle zu verwerfen.", "animatedPickConfirm": "Bestätigen", "animatedPriority": "Priorität", "animatedCanvas": "Ausgabegröße", diff --git a/release/UNIVERSAL_SpineViewer/_locales/en.json b/release/UNIVERSAL_SpineViewer/_locales/en.json index d57c9f2..3c85903 100644 --- a/release/UNIVERSAL_SpineViewer/_locales/en.json +++ b/release/UNIVERSAL_SpineViewer/_locales/en.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "This environment cannot encode WebP. Choose APNG instead.", "animatedCannotFit": "The animation cannot be reduced to {target} KB (minimum about {actual} KB). Increase the limit or shorten the frame range.", "animatedPickTitle": "Pick a thumbnail", - "animatedPickHint": "Every result keeps a 400×400 canvas; the label shows detail resolution@fps/quality/file size. Select one and press Confirm to replace the thumbnail, or cancel to discard them all.", + "animatedPickHint": "Every result keeps a {size} canvas; the label shows detail resolution@fps/quality/file size. Select one and press Confirm to replace the thumbnail, or cancel to discard them all.", "animatedPickConfirm": "Confirm", "animatedPriority": "Priority", "animatedCanvas": "Canvas size", diff --git a/release/UNIVERSAL_SpineViewer/_locales/es_ES.json b/release/UNIVERSAL_SpineViewer/_locales/es_ES.json index ff8234a..e87ec76 100644 --- a/release/UNIVERSAL_SpineViewer/_locales/es_ES.json +++ b/release/UNIVERSAL_SpineViewer/_locales/es_ES.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "Este entorno no puede codificar WebP. Selecciona APNG.", "animatedCannotFit": "No se puede reducir la animación a {target} KB (mínimo aproximado: {actual} KB). Aumenta el límite o acorta el rango.", "animatedPickTitle": "Elige una miniatura", - "animatedPickHint": "Todos los resultados mantienen un lienzo de 400×400; la etiqueta indica la resolución de detalle@fps/calidad/tamaño de archivo. Elige uno y pulsa Confirmar para aplicarlo, o cancela para descartarlos todos.", + "animatedPickHint": "Todos los resultados mantienen un lienzo de {size}; la etiqueta indica la resolución de detalle@fps/calidad/tamaño de archivo. Elige uno y pulsa Confirmar para aplicarlo, o cancela para descartarlos todos.", "animatedPickConfirm": "Confirmar", "animatedPriority": "Prioridad", "animatedCanvas": "Tamaño del lienzo", diff --git a/release/UNIVERSAL_SpineViewer/_locales/ja_JP.json b/release/UNIVERSAL_SpineViewer/_locales/ja_JP.json index 6bae31b..8e57ef7 100644 --- a/release/UNIVERSAL_SpineViewer/_locales/ja_JP.json +++ b/release/UNIVERSAL_SpineViewer/_locales/ja_JP.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "この環境では WebP をエンコードできません。APNG を選択してください。", "animatedCannotFit": "アニメーションを {target} KB まで圧縮できません(最小約 {actual} KB)。上限を増やすかフレーム範囲を短くしてください。", "animatedPickTitle": "サムネイルを選択", - "animatedPickHint": "すべての結果は 400×400 のキャンバスです。ラベルは実際のディテール解像度@fps/品質/ファイルサイズを示します。1つ選んで確認を押すと置き換え、キャンセルですべて破棄します。", + "animatedPickHint": "すべての結果は {size} のキャンバスです。ラベルは実際のディテール解像度@fps/品質/ファイルサイズを示します。1つ選んで確認を押すと置き換え、キャンセルですべて破棄します。", "animatedPickConfirm": "確認", "animatedPriority": "優先度", "animatedCanvas": "出力サイズ", diff --git a/release/UNIVERSAL_SpineViewer/_locales/ko_KR.json b/release/UNIVERSAL_SpineViewer/_locales/ko_KR.json index 98872bc..5d1e060 100644 --- a/release/UNIVERSAL_SpineViewer/_locales/ko_KR.json +++ b/release/UNIVERSAL_SpineViewer/_locales/ko_KR.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "현재 환경에서 WebP를 인코딩할 수 없습니다. APNG를 선택하세요.", "animatedCannotFit": "애니메이션을 {target}KB로 줄일 수 없습니다(최소 약 {actual}KB). 제한을 높이거나 프레임 범위를 줄이세요.", "animatedPickTitle": "썸네일 선택", - "animatedPickHint": "모든 결과의 캔버스는 400×400이며, 라벨은 실제 디테일 해상도@fps/품질/파일 크기입니다. 하나를 선택하고 확인을 누르면 적용되고, 취소하면 모두 버려집니다.", + "animatedPickHint": "모든 결과의 캔버스는 {size}이며, 라벨은 실제 디테일 해상도@fps/품질/파일 크기입니다. 하나를 선택하고 확인을 누르면 적용되고, 취소하면 모두 버려집니다.", "animatedPickConfirm": "확인", "animatedPriority": "우선 순위", "animatedCanvas": "출력 크기", diff --git a/release/UNIVERSAL_SpineViewer/_locales/ru_RU.json b/release/UNIVERSAL_SpineViewer/_locales/ru_RU.json index ff73f7b..d87df6a 100644 --- a/release/UNIVERSAL_SpineViewer/_locales/ru_RU.json +++ b/release/UNIVERSAL_SpineViewer/_locales/ru_RU.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "Эта среда не поддерживает кодирование WebP. Выберите APNG.", "animatedCannotFit": "Анимацию нельзя уменьшить до {target} КБ (минимум около {actual} КБ). Увеличьте лимит или сократите диапазон кадров.", "animatedPickTitle": "Выберите миниатюру", - "animatedPickHint": "У всех результатов холст 400×400; в подписи указаны реальное разрешение детализации@fps/качество/размер файла. Выберите результат и нажмите «Подтвердить», чтобы применить его, или отмените, чтобы всё отбросить.", + "animatedPickHint": "У всех результатов холст {size}; в подписи указаны реальное разрешение детализации@fps/качество/размер файла. Выберите результат и нажмите «Подтвердить», чтобы применить его, или отмените, чтобы всё отбросить.", "animatedPickConfirm": "Подтвердить", "animatedPriority": "Приоритет", "animatedCanvas": "Размер холста", diff --git a/release/UNIVERSAL_SpineViewer/_locales/zh_CN.json b/release/UNIVERSAL_SpineViewer/_locales/zh_CN.json index 45a2284..35531ca 100644 --- a/release/UNIVERSAL_SpineViewer/_locales/zh_CN.json +++ b/release/UNIVERSAL_SpineViewer/_locales/zh_CN.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "当前环境不支持 WebP 编码,请选择 APNG", "animatedCannotFit": "无法在保留动画的前提下压缩到 {target} KB(最小约 {actual} KB),请提高上限或缩短帧范围", "animatedPickTitle": "选择一个缩略图", - "animatedPickHint": "所有结果画布都是 400×400,标签为实际细节分辨率@帧率/质量/文件大小。点选一个结果后按确认替换缩略图,取消则全部放弃。", + "animatedPickHint": "所有结果画布都是 {size},标签为实际细节分辨率@帧率/质量/文件大小。点选一个结果后按确认替换缩略图,取消则全部放弃。", "animatedPickConfirm": "确认", "animatedPriority": "优先级别", "animatedCanvas": "输出尺寸", diff --git a/release/UNIVERSAL_SpineViewer/_locales/zh_TW.json b/release/UNIVERSAL_SpineViewer/_locales/zh_TW.json index ea2ef70..7096ce3 100644 --- a/release/UNIVERSAL_SpineViewer/_locales/zh_TW.json +++ b/release/UNIVERSAL_SpineViewer/_locales/zh_TW.json @@ -37,7 +37,7 @@ "animatedWebpUnavailable": "目前環境不支援 WebP 編碼,請選擇 APNG", "animatedCannotFit": "無法在保留動畫的情況下壓縮到 {target} KB(最小約 {actual} KB),請提高上限或縮短影格範圍", "animatedPickTitle": "選擇一個縮圖", - "animatedPickHint": "所有結果畫布都是 400×400,標籤為實際細節解析度@影格率/品質/檔案大小。點選一個結果後按確認替換縮圖,取消則全部放棄。", + "animatedPickHint": "所有結果畫布都是 {size},標籤為實際細節解析度@影格率/品質/檔案大小。點選一個結果後按確認替換縮圖,取消則全部放棄。", "animatedPickConfirm": "確認", "animatedPriority": "優先級別", "animatedCanvas": "輸出尺寸", diff --git a/release/UNIVERSAL_SpineViewer/js/animated-profiles.js b/release/UNIVERSAL_SpineViewer/js/animated-profiles.js index 1663494..d4da6ff 100644 --- a/release/UNIVERSAL_SpineViewer/js/animated-profiles.js +++ b/release/UNIVERSAL_SpineViewer/js/animated-profiles.js @@ -42,9 +42,21 @@ const DEFAULT_PRIORITY = 'resolution'; const ANIMATED_OUTPUT_SIZES = [200, 400]; const DEFAULT_OUTPUT_SIZE = 200; +/** + * 「缩略图大小」输入框的默认建议值:每秒动画配 25 KB,夹在 25–100 KB 之间。 + * 只是打开面板时的初始值,用户随时可以手动改成 10–1024 之间的任意数。 + */ +const SIZE_PER_SECOND = 25; +const SIZE_SUGGESTION_RANGE = [25, 100]; + // 相邻锚点之间插多少个采样点。数值越大,越容易压在目标体积附近,但粗估阶段耗时略增。 const PATH_STEPS_PER_SEGMENT = 6; +function suggestSize(seconds) { + const [min, max] = SIZE_SUGGESTION_RANGE; + return Math.max(min, Math.min(max, Math.round((Number(seconds) || 0) * SIZE_PER_SECOND))); +} + function animatedProfiles(priority, outputSize) { const limit = outputSize || DEFAULT_OUTPUT_SIZE; const plan = ANIMATED_PRIORITIES[priority] || ANIMATED_PRIORITIES[DEFAULT_PRIORITY]; @@ -86,7 +98,10 @@ module.exports = { DEFAULT_PRIORITY, ANIMATED_OUTPUT_SIZES, DEFAULT_OUTPUT_SIZE, + SIZE_PER_SECOND, + SIZE_SUGGESTION_RANGE, PATH_STEPS_PER_SEGMENT, animatedProfiles, expandAnimatedPath, + suggestSize, }; diff --git a/release/UNIVERSAL_SpineViewer/viewer/spine.html b/release/UNIVERSAL_SpineViewer/viewer/spine.html index 69e7ec5..a1fea37 100644 --- a/release/UNIVERSAL_SpineViewer/viewer/spine.html +++ b/release/UNIVERSAL_SpineViewer/viewer/spine.html @@ -103,7 +103,7 @@ 帧