feat: 添加图层缩略图生成时对遮罩对象的支持,优化图层对象的z-index处理
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user