@
feat(upload): 前端上传前 Canvas 压缩图片(大图缩至1920 + JPEG q=0.78) Co-Authored-By: Claude <noreply@anthropic.com> @
This commit is contained in:
parent
26443a1df5
commit
f4b417bcaf
@ -498,6 +498,31 @@ export function PhotoWallPage({ onExit, token, folderName, isAdmin, onForbidden
|
|||||||
})
|
})
|
||||||
}, [addEl, spawnPos])
|
}, [addEl, spawnPos])
|
||||||
|
|
||||||
|
/* ── 图片压缩(Canvas:缩小 + 转 JPEG)─────────────────────── */
|
||||||
|
/** 把 data URL 图片压缩后返回新 data URL(宽 > 1920 的缩到 1920,JPEG q=0.78)。
|
||||||
|
* 失败时返回原图。 */
|
||||||
|
function compressImage(dataUrl: string): Promise<string> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const img = new Image()
|
||||||
|
img.onload = () => {
|
||||||
|
try {
|
||||||
|
let w = img.naturalWidth
|
||||||
|
let h = img.naturalHeight
|
||||||
|
// 大图缩小
|
||||||
|
if (w > 1920) { h = Math.round(h * 1920 / w); w = 1920 }
|
||||||
|
const canvas = document.createElement('canvas')
|
||||||
|
canvas.width = w; canvas.height = h
|
||||||
|
const ctx = canvas.getContext('2d')
|
||||||
|
if (!ctx) { resolve(dataUrl); return }
|
||||||
|
ctx.drawImage(img, 0, 0, w, h)
|
||||||
|
resolve(canvas.toDataURL('image/jpeg', 0.78))
|
||||||
|
} catch { resolve(dataUrl) }
|
||||||
|
}
|
||||||
|
img.onerror = () => resolve(dataUrl)
|
||||||
|
img.src = dataUrl
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/* ── 图片上传 ─────────────────────────────────────────────── */
|
/* ── 图片上传 ─────────────────────────────────────────────── */
|
||||||
const handleFiles = useCallback(
|
const handleFiles = useCallback(
|
||||||
(files: FileList | File[]) => {
|
(files: FileList | File[]) => {
|
||||||
@ -511,8 +536,8 @@ export function PhotoWallPage({ onExit, token, folderName, isAdmin, onForbidden
|
|||||||
imgs.forEach((file) => {
|
imgs.forEach((file) => {
|
||||||
if (file.size > 10 * 1024 * 1024) showToast('图片较大,建议压缩后上传')
|
if (file.size > 10 * 1024 * 1024) showToast('图片较大,建议压缩后上传')
|
||||||
const reader = new FileReader()
|
const reader = new FileReader()
|
||||||
reader.onload = (ev) => {
|
reader.onload = async (ev) => {
|
||||||
const src = ev.target?.result as string
|
const rawSrc = ev.target?.result as string
|
||||||
// 个人墙有张数上限
|
// 个人墙有张数上限
|
||||||
if (maxPhotos > 0) {
|
if (maxPhotos > 0) {
|
||||||
const count = elsRef.current.filter((e) => e.type === 'photo').length
|
const count = elsRef.current.filter((e) => e.type === 'photo').length
|
||||||
@ -526,6 +551,8 @@ export function PhotoWallPage({ onExit, token, folderName, isAdmin, onForbidden
|
|||||||
showToast(`已达上限(${maxItems} 条)`)
|
showToast(`已达上限(${maxItems} 条)`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 客户端压缩(大图缩小 + 转 JPEG q=0.78)
|
||||||
|
const src = await compressImage(rawSrc)
|
||||||
const uploadFn = isPersonal
|
const uploadFn = isPersonal
|
||||||
? (t: string, d: string) => uploadPhoto(t, d)
|
? (t: string, d: string) => uploadPhoto(t, d)
|
||||||
: (t: string, d: string) => uploadFolderPhoto(t, folderName!, d)
|
: (t: string, d: string) => uploadFolderPhoto(t, folderName!, d)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user