feat: 监控上传图片压缩
This commit is contained in:
parent
dd9000bf48
commit
23c87c43e1
@ -15,6 +15,9 @@ const MONITOR_SNAPSHOT_INTERVAL = 10000
|
|||||||
const MONITOR_MSG_TYPE = 'monitorStart'
|
const MONITOR_MSG_TYPE = 'monitorStart'
|
||||||
const MONITOR_STOP_MSG_TYPE = 'monitorStop'
|
const MONITOR_STOP_MSG_TYPE = 'monitorStop'
|
||||||
const MONITOR_LOG_PREFIX = '[class-monitor]'
|
const MONITOR_LOG_PREFIX = '[class-monitor]'
|
||||||
|
const MONITOR_SNAPSHOT_TARGET_SIZE = 100 * 1024
|
||||||
|
const MONITOR_SNAPSHOT_MIN_WIDTH = 480
|
||||||
|
const MONITOR_SNAPSHOT_MIN_HEIGHT = 270
|
||||||
|
|
||||||
const monitorLog = (...args: unknown[]) => console.log(MONITOR_LOG_PREFIX, ...args)
|
const monitorLog = (...args: unknown[]) => console.log(MONITOR_LOG_PREFIX, ...args)
|
||||||
const monitorWarn = (...args: unknown[]) => console.warn(MONITOR_LOG_PREFIX, ...args)
|
const monitorWarn = (...args: unknown[]) => console.warn(MONITOR_LOG_PREFIX, ...args)
|
||||||
@ -119,20 +122,84 @@ const prepareMonitorDomForCapture = async () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvasToPngFile = (canvas: HTMLCanvasElement) =>
|
const canvasToBlob = (canvas: HTMLCanvasElement, type: string, quality?: number) =>
|
||||||
new Promise<File | null>(resolve => {
|
new Promise<Blob | null>(resolve => {
|
||||||
canvas.toBlob(blob => {
|
canvas.toBlob(
|
||||||
if (!blob) return resolve(null)
|
blob => {
|
||||||
resolve(new File([blob], `monitor-${Date.now()}.png`, { type: 'image/png' }))
|
resolve(blob)
|
||||||
}, 'image/png')
|
},
|
||||||
|
type,
|
||||||
|
quality,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const resizeCanvas = (source: HTMLCanvasElement, ratio: number) => {
|
||||||
|
const canvas = document.createElement('canvas')
|
||||||
|
canvas.width = Math.max(1, Math.round(source.width * ratio))
|
||||||
|
canvas.height = Math.max(1, Math.round(source.height * ratio))
|
||||||
|
const ctx = canvas.getContext('2d')
|
||||||
|
if (!ctx) return source
|
||||||
|
ctx.drawImage(source, 0, 0, canvas.width, canvas.height)
|
||||||
|
return canvas
|
||||||
|
}
|
||||||
|
|
||||||
|
const canvasToMonitorFile = async (canvas: HTMLCanvasElement) => {
|
||||||
|
const qualities = [0.72, 0.6, 0.5, 0.42, 0.35, 0.3, 0.25]
|
||||||
|
let current = canvas
|
||||||
|
let bestBlob: Blob | null = null
|
||||||
|
let bestInfo = {
|
||||||
|
width: canvas.width,
|
||||||
|
height: canvas.height,
|
||||||
|
quality: qualities[0],
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let resizeCount = 0; resizeCount < 8; resizeCount++) {
|
||||||
|
for (const quality of qualities) {
|
||||||
|
const blob = await canvasToBlob(current, 'image/jpeg', quality)
|
||||||
|
if (!blob) return null
|
||||||
|
if (!bestBlob || blob.size < bestBlob.size) {
|
||||||
|
bestBlob = blob
|
||||||
|
bestInfo = {
|
||||||
|
width: current.width,
|
||||||
|
height: current.height,
|
||||||
|
quality,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blob.size <= MONITOR_SNAPSHOT_TARGET_SIZE) {
|
||||||
|
monitorLog('web screenshot compressed', {
|
||||||
|
width: current.width,
|
||||||
|
height: current.height,
|
||||||
|
quality,
|
||||||
|
size: blob.size,
|
||||||
|
})
|
||||||
|
return new File([blob], `monitor-${Date.now()}.jpg`, { type: 'image/jpeg' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
current.width <= MONITOR_SNAPSHOT_MIN_WIDTH ||
|
||||||
|
current.height <= MONITOR_SNAPSHOT_MIN_HEIGHT
|
||||||
|
) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
current = resizeCanvas(current, 0.85)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bestBlob) return null
|
||||||
|
monitorWarn('web screenshot compressed but still over target', {
|
||||||
|
...bestInfo,
|
||||||
|
size: bestBlob.size,
|
||||||
|
target: MONITOR_SNAPSHOT_TARGET_SIZE,
|
||||||
|
})
|
||||||
|
return new File([bestBlob], `monitor-${Date.now()}.jpg`, { type: 'image/jpeg' })
|
||||||
|
}
|
||||||
|
|
||||||
const createWebScreenshotFile = async (): Promise<File | null> => {
|
const createWebScreenshotFile = async (): Promise<File | null> => {
|
||||||
await prepareMonitorDomForCapture()
|
await prepareMonitorDomForCapture()
|
||||||
|
|
||||||
const vw = window.innerWidth
|
const vw = window.innerWidth
|
||||||
const vh = window.innerHeight
|
const vh = window.innerHeight
|
||||||
const scale = Math.min(window.devicePixelRatio || 1, 2)
|
const scale = Math.min(window.devicePixelRatio || 1, 1)
|
||||||
monitorLog('web screenshot start', {
|
monitorLog('web screenshot start', {
|
||||||
href: window.location.href,
|
href: window.location.href,
|
||||||
viewport: `${vw}x${vh}`,
|
viewport: `${vw}x${vh}`,
|
||||||
@ -200,7 +267,7 @@ const createWebScreenshotFile = async (): Promise<File | null> => {
|
|||||||
monitorWarn('web screenshot canvas empty', index + 1)
|
monitorWarn('web screenshot canvas empty', index + 1)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const file = await canvasToPngFile(canvas)
|
const file = await canvasToMonitorFile(canvas)
|
||||||
if (file) {
|
if (file) {
|
||||||
monitorLog('web screenshot file ready', {
|
monitorLog('web screenshot file ready', {
|
||||||
attempt: index + 1,
|
attempt: index + 1,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user