画布增加的新功能

This commit is contained in:
李志鹏
2026-01-02 11:24:11 +08:00
parent 1ae365b1f3
commit f8e4ab8cdb
59 changed files with 4401 additions and 1213 deletions

View File

@@ -1,6 +1,7 @@
import { fabric } from "fabric-with-all";
import { findObjectById } from "../utils/helper";
import { createRasterizedImage } from "../utils/selectionToImage";
import { OperationType, SpecialLayerId } from "../utils/layerHelper";
/**
* 图片导出管理器
@@ -18,7 +19,7 @@ export class ExportManager {
* @param {Object} options 导出选项
* @param {Boolean} options.isContainBg 是否包含背景图层
* @param {Boolean} options.isContainFixed 是否包含固定图层
* @param {Boolean} options.isCropByBg 是否使用背景大小裁剪
* @param {Boolean} options.isCropByBg 是否使用背景大小裁剪
* @param {String} options.layerId 导出具体图层ID
* @param {Array} options.layerIdArray 导出多个图层ID数组
* @param {String} options.expPicType 导出图片类型 (png/jpg/svg)
@@ -26,7 +27,7 @@ export class ExportManager {
* @param {Boolean} options.isEnhanceImg 是否是增强图片
* @returns {String} 导出的图片数据URL
*/
exportImage(options = {}) {
async exportImage(options = {}) {
const {
isContainBg = false,
isContainFixed = false,
@@ -35,9 +36,16 @@ export class ExportManager {
layerIdArray = [],
expPicType = "png",
restoreOpacityInRedGreen = true,
isEnhanceImg, // 是否是增强图片
isEnhanceImg, // 是否是增强图片
} = options;
try {
// 查找颜色图层并隐藏
const colorLayer = this.layerManager.getLayerById(SpecialLayerId.COLOR);
if (colorLayer && colorLayer.visible) {
colorLayer.visible = false;
await this.layerManager?.updateLayersObjectsInteractivity();
}
// 检查是否为红绿图模式
const isRedGreenMode = this.layerManager?.isInRedGreenMode?.() || false;
// 如果指定了具体图层ID导出指定图层
@@ -48,7 +56,7 @@ export class ExportManager {
isRedGreenMode,
restoreOpacityInRedGreen,
isCropByBg,
isEnhanceImg, // 是否是增强图片
isEnhanceImg, // 是否是增强图片
);
}
@@ -62,7 +70,7 @@ export class ExportManager {
isRedGreenMode,
restoreOpacityInRedGreen,
isCropByBg,
isEnhanceImg, // 是否是增强图片
isEnhanceImg, // 是否是增强图片
);
}
@@ -74,7 +82,7 @@ export class ExportManager {
isRedGreenMode,
restoreOpacityInRedGreen,
isCropByBg,
isEnhanceImg, // 是否是增强图片
isEnhanceImg, // 是否是增强图片
);
} catch (error) {
console.error("导出图片失败:", error);
@@ -128,8 +136,6 @@ export class ExportManager {
objectsToExport,
expPicType,
restoreOpacityInRedGreen,
isCropByBg, // 是否使用背景大小裁剪
isEnhanceImg, // 是否是增强图片
);
}
@@ -555,37 +561,22 @@ export class ExportManager {
);
}
// 获取固定图层对象的边界矩形(包含位置、尺寸、缩放等信息)
const fixedBounds = fixedLayerObject?.getBoundingRect?.();
// 使用固定图层的实际显示尺寸作为导出画布尺寸
const canvasWidth = Math.round(fixedBounds.width);
const canvasHeight = Math.round(fixedBounds.height);
const canvasWidth = (fixedLayerObject.width);
const canvasHeight = (fixedLayerObject.height);
console.log(`红绿图模式导出,画布尺寸: ${canvasWidth}x${canvasHeight}`);
console.log("固定图层边界:", fixedBounds);
// 创建固定尺寸的临时画布
const scaleFactor = 2; // 高清导出
const tempCanvas = document.createElement("canvas");
tempCanvas.width = canvasWidth * scaleFactor;
tempCanvas.height = canvasHeight * scaleFactor;
tempCanvas.style.width = canvasWidth + "px";
tempCanvas.style.height = canvasHeight + "px";
const tempFabricCanvas = new fabric.StaticCanvas(tempCanvas, {
const tempFabricCanvas = new fabric.StaticCanvas()
tempFabricCanvas.setDimensions({
width: canvasWidth,
height: canvasHeight,
backgroundColor: null,
enableRetinaScaling: true,
// enableRetinaScaling: true,
imageSmoothingEnabled: true,
});
tempFabricCanvas.setZoom(1);
// tempFabricCanvas.setZoom(1);
console.log("==========", fixedLayerObject)
try {
// 获取裁剪路径对象(如果存在)
const clipPathObject = await this._getClipPathObject(fixedBounds);
// 克隆并添加所有对象到临时画布,需要调整位置相对于固定图层
for (let i = 0; i < objectsToExport.length; i++) {
const obj = objectsToExport[i];
@@ -596,18 +587,16 @@ export class ExportManager {
if (cloned) {
// 调整对象位置:将原画布坐标转换为以固定图层为原点的相对坐标
cloned.set({
left: cloned.left - fixedBounds.left,
top: cloned.top - fixedBounds.top,
left: canvasWidth / 2,
top: canvasHeight / 2,
scaleX: cloned.scaleX / fixedLayerObject.scaleX,
scaleY: cloned.scaleY / fixedLayerObject.scaleY,
originX: "center",
originY: "center",
});
console.log("==========", {...cloned})
// 更新对象坐标
cloned.setCoords();
// 设置裁剪路径到对象
if (clipPathObject) {
cloned.clipPath = clipPathObject;
}
tempFabricCanvas.add(cloned);
}
}
@@ -616,7 +605,7 @@ export class ExportManager {
tempFabricCanvas.renderAll();
// 生成图片
return this._generateHighQualityDataURL(tempCanvas, expPicType);
return this._generateHighQualityDataURL(tempFabricCanvas, expPicType);
} finally {
this._cleanupTempCanvas(tempFabricCanvas);
}
@@ -736,7 +725,7 @@ export class ExportManager {
*/
_cloneObjectAsync(
obj,
propertiesToInclude = ["id", "layerId", "layerName", "name"]
propertiesToInclude = ["id", "layerId", "layerName", "name", "scaleX", "scaleY"]
) {
return new Promise((resolve, reject) => {
if (!obj) {