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();}
}