import { findObjectById } from "../utils/helper"; import { findLayerRecursively } from "../utils/layerHelper"; import { restoreFabricObject } from "../utils/objectHelper"; import { createRasterizedImage } from "../utils/rasterizedImage"; /** * 缩略图管理器 - 负责生成和缓存图层和元素的预览缩略图 */ export class ThumbnailManager { constructor(canvas, options = {}) { this.canvas = canvas; this.layers = options.layers || []; // 图层管理器 this.layerThumbSize = options.layerThumbSize || { width: 48, height: 48 }; // this.layerThumbnails = new Map(); // 图层缩略图缓存 - 改成使用图层对象的thumbnailUrl属性 // 使用图层对象的thumbnailUrl属性来存储缩略图URL this.defaultThumbnail = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="; // 1x1 透明图 } /** * 生成图层缩略图 * @param {Object} layer 图层对象ID */ async generateLayerThumbnail(layerId) { const fabricObjects = this._collectLayersAndObjects(layerId); const { layer } = findLayerRecursively(this.layers.value, layerId); if (!fabricObjects || fabricObjects.length === 0) { // console.warn("⚠️ 无法生成缩略图:没有可栅格化的对象 返回空缩略图"); // 如果没有对象,返回默认缩略图 if (layer) { layer.thumbnailUrl = this.defaultThumbnail; // 更新图层对象的缩略图 } return this.defaultThumbnail; } // 延迟执行,避免阻塞UI fabricObjects.length > 0 && requestIdleCallback(() => { setTimeout(async () => { const base64 = await this._generateLayerThumbnailNow(fabricObjects, layer); // this.layerThumbnails.set(layerId, base64); try { const { layer, parent } = findLayerRecursively(this.layers.value, layerId); if (layer) { layer.thumbnailUrl = base64; // 更新图层对象的缩略图 } if (parent) { // 如果是组图层,则同步更新父图层的缩略图 this.generateLayerThumbnail(parent.id); } } catch (error) { console.error("生成图层缩略图时出错:", error); } }); }); } /** * 批量生成图层缩略图 * @param {Array} layers 图层数组 */ generateAllLayerThumbnails(layers) { if (!layers || !Array.isArray(layers)) return; requestIdleCallback(() => { setTimeout(() => { layers.forEach((layer) => { if (layer && layer.id) { this.generateLayerThumbnail(layer.id); if (layer.children && layer.children.length) { this.generateLayerThumbnail(layer.id); } } }); }); }); } // 生成图片 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: clippingMaskFabricObject || null, // 用于裁剪的对象 - 可选 trimWhitespace: true, // 是否裁剪空白区域 trimPadding: 2, // 裁剪边距 quality: 0.2, // 图像质量 format: "png", // 图像格式 scaleFactor: 0.2, // 高清倍数 - 默认是画布的高清倍数 isReturenDataURL: true, // 是否返回DataURL而不是fabric.Image对象 isThumbnail: true, // 为缩略图 }); } catch (error) { return this.defaultThumbnail; // 出错时返回默认缩略图 } } /** * 收集要栅格化的图层和对象 * @private */ _collectLayersAndObjects(layerId) { if (!layerId) { // console.warn("⚠️ 无效的图层ID,无法收集对象"); return []; } const { layer } = findLayerRecursively(this.layers.value, layerId); if (!layer) { console.warn("⚠️ 无效的图层,无法收集对象"); return []; } let layersToRasterize = []; if (layer.children && layer.children.length > 0) { // 组图层:收集自身和所有子图层 layersToRasterize = this._collectLayersToRasterize(layer); } else { // 普通图层:只收集自身 layersToRasterize = [layer]; } // 收集所有图层的fabricObjects并按画布z-index顺序排序 const allCanvasObjects = this.canvas.getObjects(); 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); if (object) { const zIndex = allCanvasObjects.indexOf(object); objectsWithZIndex.push({ object: object, zIndex: zIndex, layerObj: layer.fabricObject, }); } } if (layer.fabricObjects && layer.fabricObjects.length > 0) { layer.fabricObjects.forEach((layerObj) => { if (layerObj && layerObj.id) { const { object } = findObjectById(this.canvas, layerObj.id); if (object) { // 获取对象在画布中的z-index(数组索引) const zIndex = allCanvasObjects.indexOf(object); objectsWithZIndex.push({ object: object, zIndex: zIndex, layerObj: layerObj, }); } } }); } }); // 按z-index排序,确保保持原有的渲染顺序 objectsWithZIndex.sort((a, b) => a.zIndex - b.zIndex); // 提取排序后的对象 const objectsToRasterize = objectsWithZIndex.map((item) => item.object); // console.log( // `📊 收集到 ${layersToRasterize.length} 个图层,${objectsToRasterize.length} 个对象进行栅格化` // ); // console.log( // "🔢 对象z-index顺序:", // objectsWithZIndex.map((item) => ({ // id: item.object.id, // type: item.object.type, // zIndex: item.zIndex, // })) // ); return objectsToRasterize; } /** * 收集要栅格化的图层(递归收集子图层) * @param {Object} sourceLayer 源图层 * @returns {Array} 图层数组 * @private */ _collectLayersToRasterize(sourceLayer) { const result = [sourceLayer]; // 如果是组图层,收集所有子图层 if (sourceLayer.children && sourceLayer.children.length > 0) { sourceLayer.children.forEach((childLayer) => { if (childLayer) { result.push(...this._collectLayersToRasterize(childLayer)); } }); } return result; } /** * 获取图层缩略图 * @param {String} layerId 图层ID * @returns {String|null} 缩略图URL或null */ getLayerThumbnail(layerId) { if (!layerId) return null; // return this.layerThumbnails.get(layerId) || null; } /** * 清除图层缩略图 * @param {String} layerId 图层ID */ clearLayerThumbnail(layerId) { if (layerId && this.layerThumbnails.has(layerId)) { // this.layerThumbnails.delete(layerId); } } /** * 清除所有缩略图 */ clearAllThumbnails() { // this.layerThumbnails.clear(); } /** * 释放资源 */ dispose() { this.clearAllThumbnails(); this.canvas = null; } }