import { image } from '@kit.ImageKit';
import { componentSnapshot, window } from '@kit.ArkUI';
import { AppUtil } from './AppUtil';
import { ArrayUtil } from './ArrayUtil';/*** 组件截图和窗口截图工具类* @author 鸿蒙布道师* @since 2025/04/28*/
export class SnapshotUtil {private static callbacks: VoidCallback[] = []; // 缓存的截图回调列表。private static snapshotCallback: VoidCallback | undefined; // 全局的截图监听回调。/*** 获取已加载组件的截图(异步方式)。* @param id 目标组件的唯一标识。* @param options 截图相关的自定义参数。* @returns 返回 Promise<image.PixelMap> 截图结果。*/static async get(id: string, options?: componentSnapshot.SnapshotOptions): Promise<image.PixelMap> {if (!id) {throw new Error('Component ID cannot be empty.');}return componentSnapshot.get(id, options);}/*** 获取已加载组件的截图(同步方式)。* @param id 目标组件的唯一标识。* @param options 截图相关的自定义参数。* @returns 返回 Promise<image.PixelMap> 截图结果。*/static getSync(id: string, options?: componentSnapshot.SnapshotOptions): Promise<image.PixelMap> {if (!id) {throw new Error('Component ID cannot be empty.');}return componentSnapshot.get(id, options);}/*** 渲染 CustomBuilder 自定义组件并获取其截图。* @param builder 自定义组件构建函数。* @param delay 触发截图指令的延迟时间(默认值:300 毫秒)。* @param checkImageStatus 是否校验图片解码状态(默认值:false)。* @param options 截图相关的自定义参数。* @returns 返回 Promise<image.PixelMap> 截图结果。*/static createFromBuilder(builder: CustomBuilder,delay: number = 300,checkImageStatus: boolean = false,options?: componentSnapshot.SnapshotOptions): Promise<image.PixelMap> {if (!builder) {throw new Error('CustomBuilder cannot be undefined.');}return componentSnapshot.createFromBuilder(builder, delay, checkImageStatus, options);}/*** 获取窗口截图(异步方式)。* @param windowClass 窗口实例(默认为主窗口)。* @returns 返回 Promise<image.PixelMap> 截图结果。*/static async snapshot(windowClass?: window.Window): Promise<image.PixelMap> {const targetWindow = windowClass ?? AppUtil.getMainWindow();if (!targetWindow) {throw new Error('Target window is not available.');}return targetWindow.snapshot();}/*** 开启系统截屏事件的监听。* @param callback 截图回调函数。*/static onSnapshotListener(callback: VoidCallback): void {if (!callback) {throw new Error('Callback function cannot be undefined.');}if (!ArrayUtil.contains(SnapshotUtil.callbacks, callback)) {SnapshotUtil.callbacks.push(callback);}if (!SnapshotUtil.snapshotCallback) {SnapshotUtil.snapshotCallback = () => {SnapshotUtil.callbacks.forEach((cb) => cb?.());};AppUtil.getMainWindow()?.on('screenshot', SnapshotUtil.snapshotCallback);}}/*** 关闭系统截屏事件的监听。* @param callback 要移除的监听回调(如果为空,则移除所有监听)。*/static removeSnapshotListener(callback?: VoidCallback): void {if (callback) {ArrayUtil.remove(SnapshotUtil.callbacks, callback);} else {SnapshotUtil.callbacks = [];}if (SnapshotUtil.callbacks.length === 0) {const mainWindow = AppUtil.getMainWindow();if (mainWindow) {if (SnapshotUtil.snapshotCallback) {mainWindow.off('screenshot', SnapshotUtil.snapshotCallback);} else {mainWindow.off('screenshot');}SnapshotUtil.snapshotCallback = undefined;}}}/*** 检查窗口是否可用。* @param windowClass 窗口实例。* @returns 如果窗口可用返回 true,否则返回 false。*/private static isWindowAvailable(windowClass?: window.Window): boolean {return !!windowClass || !!AppUtil.getMainWindow();}
}
代码如下:
import { image } from '@kit.ImageKit';
import { componentSnapshot, window } from '@kit.ArkUI';
import { AppUtil } from './AppUtil';
import { ArrayUtil } from './ArrayUtil';/*** 组件截图和窗口截图工具类* @author 鸿蒙布道师* @since 2025/04/28*/
export class SnapshotUtil {private static callbacks: VoidCallback[] = []; // 缓存的截图回调列表。private static snapshotCallback: VoidCallback | undefined; // 全局的截图监听回调。/*** 获取已加载组件的截图(异步方式)。* @param id 目标组件的唯一标识。* @param options 截图相关的自定义参数。* @returns 返回 Promise<image.PixelMap> 截图结果。*/static async get(id: string, options?: componentSnapshot.SnapshotOptions): Promise<image.PixelMap> {if (!id) {throw new Error('Component ID cannot be empty.');}return componentSnapshot.get(id, options);}/*** 获取已加载组件的截图(同步方式)。* @param id 目标组件的唯一标识。* @param options 截图相关的自定义参数。* @returns 返回 Promise<image.PixelMap> 截图结果。*/static getSync(id: string, options?: componentSnapshot.SnapshotOptions): Promise<image.PixelMap> {if (!id) {throw new Error('Component ID cannot be empty.');}return componentSnapshot.get(id, options);}/*** 渲染 CustomBuilder 自定义组件并获取其截图。* @param builder 自定义组件构建函数。* @param delay 触发截图指令的延迟时间(默认值:300 毫秒)。* @param checkImageStatus 是否校验图片解码状态(默认值:false)。* @param options 截图相关的自定义参数。* @returns 返回 Promise<image.PixelMap> 截图结果。*/static createFromBuilder(builder: CustomBuilder,delay: number = 300,checkImageStatus: boolean = false,options?: componentSnapshot.SnapshotOptions): Promise<image.PixelMap> {if (!builder) {throw new Error('CustomBuilder cannot be undefined.');}return componentSnapshot.createFromBuilder(builder, delay, checkImageStatus, options);}/*** 获取窗口截图(异步方式)。* @param windowClass 窗口实例(默认为主窗口)。* @returns 返回 Promise<image.PixelMap> 截图结果。*/static async snapshot(windowClass?: window.Window): Promise<image.PixelMap> {const targetWindow = windowClass ?? AppUtil.getMainWindow();if (!targetWindow) {throw new Error('Target window is not available.');}return targetWindow.snapshot();}/*** 开启系统截屏事件的监听。* @param callback 截图回调函数。*/static onSnapshotListener(callback: VoidCallback): void {if (!callback) {throw new Error('Callback function cannot be undefined.');}if (!ArrayUtil.contains(SnapshotUtil.callbacks, callback)) {SnapshotUtil.callbacks.push(callback);}if (!SnapshotUtil.snapshotCallback) {SnapshotUtil.snapshotCallback = () => {SnapshotUtil.callbacks.forEach((cb) => cb?.());};AppUtil.getMainWindow()?.on('screenshot', SnapshotUtil.snapshotCallback);}}/*** 关闭系统截屏事件的监听。* @param callback 要移除的监听回调(如果为空,则移除所有监听)。*/static removeSnapshotListener(callback?: VoidCallback): void {if (callback) {ArrayUtil.remove(SnapshotUtil.callbacks, callback);} else {SnapshotUtil.callbacks = [];}if (SnapshotUtil.callbacks.length === 0) {const mainWindow = AppUtil.getMainWindow();if (mainWindow) {if (SnapshotUtil.snapshotCallback) {mainWindow.off('screenshot', SnapshotUtil.snapshotCallback);} else {mainWindow.off('screenshot');}SnapshotUtil.snapshotCallback = undefined;}}}/*** 检查窗口是否可用。* @param windowClass 窗口实例。* @returns 如果窗口可用返回 true,否则返回 false。*/private static isWindowAvailable(windowClass?: window.Window): boolean {return !!windowClass || !!AppUtil.getMainWindow();}
}