From b3f4e42716fe1d998d093e7556897bdb2e9037a9 Mon Sep 17 00:00:00 2001 From: roymondchen Date: Thu, 9 Apr 2026 15:05:41 +0800 Subject: [PATCH] =?UTF-8?q?feat(stage):=20=E6=94=AF=E6=8C=81=E5=B0=86?= =?UTF-8?q?=E6=8C=87=E5=AE=9Aid=E7=9A=84dom=E7=94=9F=E6=88=90=E5=9B=BE?= =?UTF-8?q?=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/stage/package.json | 1 + packages/stage/src/StageCore.ts | 16 ++++++++++++++++ packages/stage/src/StageRender.ts | 31 +++++++++++++++++++++++++++++++ pnpm-lock.yaml | 8 ++++++++ 4 files changed, 56 insertions(+) diff --git a/packages/stage/package.json b/packages/stage/package.json index 709dbad4..57f46cb8 100644 --- a/packages/stage/package.json +++ b/packages/stage/package.json @@ -31,6 +31,7 @@ "dependencies": { "@scena/guides": "^0.29.2", "events": "^3.3.0", + "@zumer/snapdom": "^2.8.0", "keycon": "^1.4.0", "lodash-es": "^4.17.21", "moveable": "^0.53.0", diff --git a/packages/stage/src/StageCore.ts b/packages/stage/src/StageCore.ts index 68b2d00b..5198448e 100644 --- a/packages/stage/src/StageCore.ts +++ b/packages/stage/src/StageCore.ts @@ -18,6 +18,7 @@ import { EventEmitter } from 'events'; +import { SnapdomOptions } from '@zumer/snapdom'; import type { MoveableOptions, OnDragStart } from 'moveable'; import type { Id } from '@tmagic/core'; @@ -272,6 +273,21 @@ export default class StageCore extends EventEmitter { this.renderer?.reloadIframe(url); } + /** + * 将指定id的dom元素生成为图片 + */ + public async getElementImage( + id: Id, + type: 'download' | 'raw' | 'svg' | 'canvas' | 'png' | 'jpeg' | 'webp' | 'blob' = 'png', + options: SnapdomOptions = {}, + ) { + if (!this.renderer) { + throw new Error('Renderer is not initialized'); + } + + return this.renderer.getElementImage(id, type, options); + } + /** * 销毁实例 */ diff --git a/packages/stage/src/StageRender.ts b/packages/stage/src/StageRender.ts index c9ce8b15..92fa06e5 100644 --- a/packages/stage/src/StageRender.ts +++ b/packages/stage/src/StageRender.ts @@ -18,6 +18,8 @@ import { EventEmitter } from 'events'; +import { snapdom, SnapdomOptions } from '@zumer/snapdom'; + import type { Id } from '@tmagic/core'; import { getElById, getHost, guid, injectStyle, isSameDomain } from '@tmagic/core'; @@ -162,6 +164,35 @@ export default class StageRender extends EventEmitter { return getElById()(this.getDocument(), id); } + /** + * 将指定id的dom元素生成为图片 + * @param id 目标元素的id + * @param options 图片生成选项 + * @returns data URL 格式的图片数据 + */ + public async getElementImage( + id: Id, + type: 'download' | 'raw' | 'svg' | 'canvas' | 'png' | 'jpeg' | 'webp' | 'blob' = 'png', + options: SnapdomOptions = {}, + ) { + const el = this.getTargetElement(id); + if (!el) { + throw new Error(`Element with id "${id}" not found`); + } + + el.scrollIntoView(); + + const toFunc = `to${type.charAt(0).toUpperCase() + type.slice(1)}`; + + const result = await snapdom(el, options); + + if (toFunc in result) { + return result[toFunc](); + } + + throw new Error(`Invalid type: ${type}`); + } + public postTmagicRuntimeReady() { this.contentWindow = this.iframe?.contentWindow as RuntimeWindow; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d59df22f..137318c7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -460,6 +460,9 @@ importers: '@tmagic/core': specifier: workspace:* version: link:../core + '@zumer/snapdom': + specifier: ^2.8.0 + version: 2.8.0 events: specifier: ^3.3.0 version: 3.3.0 @@ -3652,6 +3655,9 @@ packages: '@vueuse/shared@9.13.0': resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==} + '@zumer/snapdom@2.8.0': + resolution: {integrity: sha512-NhztgFDNfOkFt8Ox9PIJ1IwggyMui5UDazysOgZD7FSGL0G7H8U+J3ft0iecxAS8daj5aC62i3blaTk7s2GcpA==} + JSONStream@1.3.5: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true @@ -9482,6 +9488,8 @@ snapshots: - '@vue/composition-api' - vue + '@zumer/snapdom@2.8.0': {} + JSONStream@1.3.5: dependencies: jsonparse: 1.3.1