feat: 添加图层缩略图生成时对遮罩对象的支持,优化图层对象的z-index处理

This commit is contained in:
bighuixiang
2025-07-15 00:15:55 +08:00
parent fc9a3eddc2
commit e31a619bd6
2 changed files with 72 additions and 4 deletions

View File

@@ -228,6 +228,18 @@ export class RasterizeLayerCommand extends Command {
const objectsWithZIndex = []; const objectsWithZIndex = [];
this.layersToRasterize.forEach((layer) => { 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) { if (layer.fabricObjects && layer.fabricObjects.length > 0) {
layer.fabricObjects.forEach((layerObj) => { layer.fabricObjects.forEach((layerObj) => {
if (layerObj && layerObj.id) { if (layerObj && layerObj.id) {
@@ -459,11 +471,27 @@ export class ExportLayerToImageCommand extends Command {
this.canvas.discardActiveObject(); this.canvas.discardActiveObject();
this.canvas.renderAll(); 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({ const imageBase64 = await createRasterizedImage({
canvas: this.canvas, canvas: this.canvas,
fabricObjects: this.objectsToRasterize, fabricObjects: this.objectsToRasterize,
isReturenDataURL: true, isReturenDataURL: true,
maskObject: clippingMaskFabricObject || null, // 不处理遮罩
}); });
// 模拟浏览器下载 // 模拟浏览器下载
@@ -504,6 +532,18 @@ export class ExportLayerToImageCommand extends Command {
const objectsWithZIndex = []; const objectsWithZIndex = [];
this.layersToRasterize.forEach((layer) => { 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) { if (layer.fabricObjects && layer.fabricObjects.length > 0) {
layer.fabricObjects.forEach((layerObj) => { layer.fabricObjects.forEach((layerObj) => {
if (layerObj && layerObj.id) { if (layerObj && layerObj.id) {

View File

@@ -1,5 +1,6 @@
import { findObjectById } from "../utils/helper"; import { findObjectById } from "../utils/helper";
import { findLayerRecursively } from "../utils/layerHelper"; import { findLayerRecursively } from "../utils/layerHelper";
import { restoreFabricObject } from "../utils/objectHelper";
import { createRasterizedImage } from "../utils/rasterizedImage"; import { createRasterizedImage } from "../utils/rasterizedImage";
/** /**
@@ -23,11 +24,11 @@ export class ThumbnailManager {
*/ */
async generateLayerThumbnail(layerId) { async generateLayerThumbnail(layerId) {
const fabricObjects = this._collectLayersAndObjects(layerId); const fabricObjects = this._collectLayersAndObjects(layerId);
const { layer } = findLayerRecursively(this.layers.value, layerId);
if (!fabricObjects || fabricObjects.length === 0) { if (!fabricObjects || fabricObjects.length === 0) {
console.warn("⚠️ 无法生成缩略图:没有可栅格化的对象 返回空缩略图"); console.warn("⚠️ 无法生成缩略图:没有可栅格化的对象 返回空缩略图");
// 如果没有对象,返回默认缩略图 // 如果没有对象,返回默认缩略图
const { layer } = findLayerRecursively(this.layers.value, layerId);
if (layer) { if (layer) {
layer.thumbnailUrl = this.defaultThumbnail; // 更新图层对象的缩略图 layer.thumbnailUrl = this.defaultThumbnail; // 更新图层对象的缩略图
} }
@@ -38,7 +39,7 @@ export class ThumbnailManager {
fabricObjects.length > 0 && fabricObjects.length > 0 &&
requestIdleCallback(() => { requestIdleCallback(() => {
setTimeout(async () => { setTimeout(async () => {
const base64 = await this._generateLayerThumbnailNow(fabricObjects); const base64 = await this._generateLayerThumbnailNow(fabricObjects, layer);
// this.layerThumbnails.set(layerId, base64); // this.layerThumbnails.set(layerId, base64);
try { try {
const { layer, parent } = findLayerRecursively(this.layers.value, layerId); 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) { if (!fabricObjects || fabricObjects.length === 0) {
console.warn("⚠️ 没有对象需要生成缩略图,返回默认缩略图"); console.warn("⚠️ 没有对象需要生成缩略图,返回默认缩略图");
return this.defaultThumbnail; return this.defaultThumbnail;
} }
try { 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({ return await createRasterizedImage({
canvas: this.canvas, // 画布对象 必填 canvas: this.canvas, // 画布对象 必填
fabricObjects, // 要栅格化的对象列表 - 按顺序 必填 fabricObjects, // 要栅格化的对象列表 - 按顺序 必填
// maskObject = null, // 用于裁剪的对象 - 可选 // TODO: 后期看是否需要裁剪 maskObject: clippingMaskFabricObject || null, // 用于裁剪的对象 - 可选
trimWhitespace: true, // 是否裁剪空白区域 trimWhitespace: true, // 是否裁剪空白区域
trimPadding: 2, // 裁剪边距 trimPadding: 2, // 裁剪边距
quality: 0.2, // 图像质量 quality: 0.2, // 图像质量
@@ -128,6 +143,19 @@ export class ThumbnailManager {
const objectsWithZIndex = []; const objectsWithZIndex = [];
layersToRasterize.forEach((layer) => { 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) { if (layer.fabricObject) {
// 如果图层本身有fabricObject直接添加 // 如果图层本身有fabricObject直接添加
const { object } = findObjectById(this.canvas, layer.fabricObject.id); const { object } = findObjectById(this.canvas, layer.fabricObject.id);