From e31a619bd698d99ceb8088e424de98cb25f61ce7 Mon Sep 17 00:00:00 2001 From: bighuixiang <472705331@qq.com> Date: Tue, 15 Jul 2025 00:15:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=9B=BE=E5=B1=82?= =?UTF-8?q?=E7=BC=A9=E7=95=A5=E5=9B=BE=E7=94=9F=E6=88=90=E6=97=B6=E5=AF=B9?= =?UTF-8?q?=E9=81=AE=E7=BD=A9=E5=AF=B9=E8=B1=A1=E7=9A=84=E6=94=AF=E6=8C=81?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96=E5=9B=BE=E5=B1=82=E5=AF=B9=E8=B1=A1?= =?UTF-8?q?=E7=9A=84z-index=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commands/RasterizeLayerCommand.js | 40 +++++++++++++++++++ .../CanvasEditor/managers/ThumbnailManager.js | 36 +++++++++++++++-- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/component/Canvas/CanvasEditor/commands/RasterizeLayerCommand.js b/src/component/Canvas/CanvasEditor/commands/RasterizeLayerCommand.js index 6c5d7259..925b7540 100644 --- a/src/component/Canvas/CanvasEditor/commands/RasterizeLayerCommand.js +++ b/src/component/Canvas/CanvasEditor/commands/RasterizeLayerCommand.js @@ -228,6 +228,18 @@ export class RasterizeLayerCommand extends Command { const objectsWithZIndex = []; this.layersToRasterize.forEach((layer) => { + if (layer.fill) { + const { object } = findObjectById(this.canvas, layer.fill.id); + if (object) { + // 获取对象在画布中的z-index(数组索引) + const zIndex = allCanvasObjects.indexOf(object); + objectsWithZIndex.push({ + object: object, + zIndex: zIndex, + layerObj: layer.fill, + }); + } + } if (layer.fabricObjects && layer.fabricObjects.length > 0) { layer.fabricObjects.forEach((layerObj) => { if (layerObj && layerObj.id) { @@ -459,11 +471,27 @@ export class ExportLayerToImageCommand extends Command { this.canvas.discardActiveObject(); this.canvas.renderAll(); + // 重新创建遮罩对象 + let clippingMaskFabricObject = null; + if (this.layer?.clippingMask) { + // 重新创建遮罩对象 + clippingMaskFabricObject = await restoreFabricObject(this.layer?.clippingMask, this.canvas); + + clippingMaskFabricObject.clipPath = null; + clippingMaskFabricObject.set({ + absolutePositioned: true, + }); + + clippingMaskFabricObject.dirty = true; + clippingMaskFabricObject.setCoords(); + } + // 创建图像 const imageBase64 = await createRasterizedImage({ canvas: this.canvas, fabricObjects: this.objectsToRasterize, isReturenDataURL: true, + maskObject: clippingMaskFabricObject || null, // 不处理遮罩 }); // 模拟浏览器下载 @@ -504,6 +532,18 @@ export class ExportLayerToImageCommand extends Command { const objectsWithZIndex = []; this.layersToRasterize.forEach((layer) => { + if (layer.fill) { + const { object } = findObjectById(this.canvas, layer.fill.id); + if (object) { + // 获取对象在画布中的z-index(数组索引) + const zIndex = allCanvasObjects.indexOf(object); + objectsWithZIndex.push({ + object: object, + zIndex: zIndex, + layerObj: layer.fill, + }); + } + } if (layer.fabricObjects && layer.fabricObjects.length > 0) { layer.fabricObjects.forEach((layerObj) => { if (layerObj && layerObj.id) { diff --git a/src/component/Canvas/CanvasEditor/managers/ThumbnailManager.js b/src/component/Canvas/CanvasEditor/managers/ThumbnailManager.js index bb8840dd..79f41375 100644 --- a/src/component/Canvas/CanvasEditor/managers/ThumbnailManager.js +++ b/src/component/Canvas/CanvasEditor/managers/ThumbnailManager.js @@ -1,5 +1,6 @@ import { findObjectById } from "../utils/helper"; import { findLayerRecursively } from "../utils/layerHelper"; +import { restoreFabricObject } from "../utils/objectHelper"; import { createRasterizedImage } from "../utils/rasterizedImage"; /** @@ -23,11 +24,11 @@ export class ThumbnailManager { */ async generateLayerThumbnail(layerId) { const fabricObjects = this._collectLayersAndObjects(layerId); + const { layer } = findLayerRecursively(this.layers.value, layerId); if (!fabricObjects || fabricObjects.length === 0) { console.warn("⚠️ 无法生成缩略图:没有可栅格化的对象 返回空缩略图"); // 如果没有对象,返回默认缩略图 - const { layer } = findLayerRecursively(this.layers.value, layerId); if (layer) { layer.thumbnailUrl = this.defaultThumbnail; // 更新图层对象的缩略图 } @@ -38,7 +39,7 @@ export class ThumbnailManager { fabricObjects.length > 0 && requestIdleCallback(() => { setTimeout(async () => { - const base64 = await this._generateLayerThumbnailNow(fabricObjects); + const base64 = await this._generateLayerThumbnailNow(fabricObjects, layer); // this.layerThumbnails.set(layerId, base64); try { const { layer, parent } = findLayerRecursively(this.layers.value, layerId); @@ -79,16 +80,30 @@ export class ThumbnailManager { } // 生成图片 - async _generateLayerThumbnailNow(fabricObjects) { + async _generateLayerThumbnailNow(fabricObjects, layer) { if (!fabricObjects || fabricObjects.length === 0) { console.warn("⚠️ 没有对象需要生成缩略图,返回默认缩略图"); return this.defaultThumbnail; } try { + let clippingMaskFabricObject = null; + if (layer?.clippingMask) { + // 重新创建遮罩对象 + clippingMaskFabricObject = await restoreFabricObject(layer?.clippingMask, this.canvas); + + clippingMaskFabricObject.clipPath = null; + clippingMaskFabricObject.set({ + absolutePositioned: true, + }); + + clippingMaskFabricObject.dirty = true; + clippingMaskFabricObject.setCoords(); + } + return await createRasterizedImage({ canvas: this.canvas, // 画布对象 必填 fabricObjects, // 要栅格化的对象列表 - 按顺序 必填 - // maskObject = null, // 用于裁剪的对象 - 可选 // TODO: 后期看是否需要裁剪 + maskObject: clippingMaskFabricObject || null, // 用于裁剪的对象 - 可选 trimWhitespace: true, // 是否裁剪空白区域 trimPadding: 2, // 裁剪边距 quality: 0.2, // 图像质量 @@ -128,6 +143,19 @@ export class ThumbnailManager { const objectsWithZIndex = []; layersToRasterize.forEach((layer) => { + if (layer.fill) { + const { object } = findObjectById(this.canvas, layer.fill.id); + if (object) { + // 获取对象在画布中的z-index(数组索引) + const zIndex = allCanvasObjects.indexOf(object); + objectsWithZIndex.push({ + object: object, + zIndex: zIndex, + layerObj: layer.fill, + }); + } + } + if (layer.fabricObject) { // 如果图层本身有fabricObject,直接添加 const { object } = findObjectById(this.canvas, layer.fabricObject.id);