fix(capture): resize charts before screenshots

This commit is contained in:
digua committed 2026-06-12 11:36:46 +08:00
1 parent 56693685fa
commit fc2ecf7b27
3 files changed
+47 -10

No files matched your search

+3 -10
View File
@@ -4,6 +4,7 @@
*/
import { ref } from 'vue'
import { captureAsImageData } from '@/utils/snapCapture'
import { waitForCaptureLayoutStabilization } from '@/utils/captureLayout'
import { useToast } from '@/composables/useToast'
import { useLayoutStore } from '@/stores/layout'
import { usePlatformService } from '@/services'
@@ -149,7 +150,6 @@ export function useScreenCapture() {
}
// 移动端宽度适配(渐进式缩放)
let appliedMobileWidth = false
if (options?.mobileWidth) {
const baseWidth = typeof options.mobileWidth === 'number' ? options.mobileWidth : DEFAULT_MOBILE_MAX_WIDTH
@@ -166,7 +166,6 @@ export function useScreenCapture() {
element.style.width = `${targetWidth}px`
element.style.minWidth = `${targetWidth}px`
element.style.maxWidth = `${targetWidth}px`
appliedMobileWidth = true
}
}
@@ -402,14 +401,7 @@ export function useScreenCapture() {
}
try {
// 如果应用了移动端宽度,等待 DOM 重新布局
if (appliedMobileWidth) {
await new Promise<void>((resolve) => {
requestAnimationFrame(() => {
requestAnimationFrame(() => resolve())
})
})
}
await waitForCaptureLayoutStabilization()
const imageData = await captureAsImageData(element, {
maxExportWidth: options?.maxExportWidth,
@@ -492,6 +484,7 @@ export function useScreenCapture() {
for (const el of hiddenElements) {
el.classList.remove('__capture-hidden__')
}
await waitForCaptureLayoutStabilization()
isCapturing.value = false
}
}
+20
View File
@@ -0,0 +1,20 @@
import { describe, it } from 'node:test'
import assert from 'node:assert/strict'
import { waitForCaptureLayoutStabilization } from './captureLayout'
describe('waitForCaptureLayoutStabilization', () => {
it('waits for layout, dispatches resize, then waits for chart repaint', async () => {
const calls: string[] = []
await waitForCaptureLayoutStabilization({
waitFrame: async () => {
calls.push('frame')
},
dispatchResize: () => {
calls.push('resize')
},
})
assert.deepEqual(calls, ['frame', 'resize', 'frame'])
})
})
+24
View File
@@ -0,0 +1,24 @@
interface CaptureLayoutStabilizationOptions {
waitFrame?: () => Promise<void>
dispatchResize?: () => void
}
function waitAnimationFrame(): Promise<void> {
return new Promise((resolve) => {
requestAnimationFrame(() => resolve())
})
}
function dispatchWindowResize() {
window.dispatchEvent(new Event('resize'))
}
export async function waitForCaptureLayoutStabilization(options?: CaptureLayoutStabilizationOptions): Promise<void> {
const waitFrame = options?.waitFrame ?? waitAnimationFrame
const dispatchResize = options?.dispatchResize ?? dispatchWindowResize
// 截图前会临时修改 padding/overflow,先等一次布局完成,再通知 ECharts 按新容器宽度重绘。
await waitFrame()
dispatchResize()
await waitFrame()
}