导出印花等所有信息

This commit is contained in:
李志鹏
2026-01-06 14:17:04 +08:00
parent 73aca07391
commit 466d278b29
12 changed files with 301 additions and 111 deletions

View File

@@ -30,7 +30,9 @@ import {
palletToFill,
fillToCssStyle,
calculateRotatedTopLeftDeg,
calculateCenterPoint,
createPatternTransform,
getTransformScaleAngle,
base64ToCanvas,
} from "../utils/helper";
import { ChangeFixedImageCommand } from "../commands/ObjectLayerCommands";
@@ -566,10 +568,10 @@ export class CanvasManager {
}
// 更新颜色层信息
// const colorObject = this.getLayerObjectById(SpecialLayerId.COLOR);
// if(colorObject){
// await this.setObjecCliptInfo(colorObject);
// }
const colorObject = this.getLayerObjectById(SpecialLayerId.COLOR);
if(colorObject){
await this.setObjecCliptInfo(colorObject);
}
const groupLayer = this.layerManager.getLayerById(SpecialLayerId.SPECIAL_GROUP);
if(groupLayer){
const groupRect = new fabric.Rect({});
@@ -808,6 +810,13 @@ export class CanvasManager {
return layerObjectByLayerId;
}
getObjectsByIds(ids){
const objects = this.canvas.getObjects().filter((obj) => {
return ids.includes(obj.id);
});
return objects;
}
/**
* 更新蒙层位置
* @param {Object} backgroundLayerObject 背景层对象
@@ -936,6 +945,7 @@ export class CanvasManager {
options.restoreOpacityInRedGreen !== undefined
? options.restoreOpacityInRedGreen
: false, // 默认在红绿图模式下恢复透明度
excludedLayers: [SpecialLayerId.SPECIAL_GROUP],
};
// 如果在红绿图模式下且没有指定具体的图层,自动包含所有普通图层
@@ -966,6 +976,22 @@ export class CanvasManager {
}
}
/**
* 导出所有信息
* @returns {Object} 包含所有图层信息的对象
*/
async exportAllInfo() {
// 导出颜色图层信息
const color = await this.exportColorLayer().catch(() => (null));
// 导出印花和元素图层信息
const printTrimsData = await this.exportPrintTrimsLayers().catch(() => ({prints: null, trims: null}));
return {
color,
...printTrimsData,
};
}
/**
* 导出颜色图层
* @returns {Object} 导出的颜色图层数据URL
@@ -980,13 +1006,12 @@ export class CanvasManager {
console.warn("颜色图层不存在,请确保已添加颜色图层");
return Promise.reject("颜色图层不存在");
}
const color = fillToCssStyle(object.fill)
const css = fillToCssStyle(object.fill)
const canvas = new fabric.StaticCanvas();
canvas.setDimensions({
width: object.width,
height: object.height,
backgroundColor: null,
// enableRetinaScaling: true,
imageSmoothingEnabled: true,
});
const cloneObject = await new Promise((resolve, reject) => {
@@ -1007,9 +1032,75 @@ export class CanvasManager {
quality: 1,
});
canvas.clear();
return {color, base64};
const color = object.originColor;
return {css, base64, color};
}
/**
* 导出印花和元素图层
*/
async exportPrintTrimsLayers() {
const object = this.layerManager.getLayerById(SpecialLayerId.SPECIAL_GROUP);
if(!object) return Promise.reject("印花和元素图层组不存在");
const ids = object.children.map((v) => v.id);
const objects = this.getObjectsByIds(ids).filter((v) => !!v.sourceData);
const fixedLayerObj = this.getFixedLayerObject();
if(!fixedLayerObj) return Promise.reject("固定图层不存在");
const flWidth = fixedLayerObj.width
const flHeight = fixedLayerObj.height
const flTop = fixedLayerObj.top
const flLeft = fixedLayerObj.left
const flScaleX = fixedLayerObj.scaleX
const flScaleY = fixedLayerObj.scaleY
const prints = [];
const trims = [];
objects.forEach((v) => {
const obj = {
ifSingle: v.sourceData.ifSingle,
level2Type: v.sourceData.level2Type,
designType: v.sourceData.designType,
path: v.sourceData.path,
location: [0, 0],
scale: [0, 0],
angle: v.angle,
name: v.sourceData.name,
}
if(obj.ifSingle){
let left = (v.left - (flLeft - flWidth * flScaleX / 2));
let top = (v.top - (flTop - flHeight * flScaleY / 2));
let width = (v.width * v.scaleX);
let height = (v.height * v.scaleY);
let {x:cx, y:cy} = calculateCenterPoint(width, height, left, top, v.angle);
let x = (cx-width/2) / flScaleX;
let y = (cy-height/2) / flScaleY;
obj.location = [x, y];
obj.scale = [(v.width * v.scaleX) / (flWidth * flScaleX), (v.height * v.scaleY) / (flHeight * flScaleY)];
}else{
let fill = v.fill;
let fill_ = v.fill_;
if(!fill || !fill_) return;
let {scale, angle} = getTransformScaleAngle(fill.patternTransform);
let scaleX = scale * 5 * v.fill_.width / flWidth;
let scaleY = scale * 5 * v.fill_.height / flHeight;
let scaleXY = flWidth > flHeight ? scaleX : scaleY;
let left = fill.offsetX + v.fill_.width * scale / 2;
let top = fill.offsetY + v.fill_.height * scale / 2;
obj.scale = [scaleXY, scaleXY];
obj.angle = angle;
obj.location = [left, top];
}
if(obj.level2Type === "Pattern"){
prints.push(obj);
}else if(obj.level2Type === "Embroidery"){
trims.push(obj);
}
})
return {prints, trims};
}
dispose() {
// 释放导出管理器资源
if (this.exportManager) {
@@ -1126,6 +1217,12 @@ export class CanvasManager {
"erasable",
"customType",
"fill_",
"scaleX",
"scaleY",
"top",
"left",
"width",
"height",
]),
layers: simplifyLayersData, // 简化图层数据
// layers: JSON.stringify(JSON.parse(JSON.stringify(this.layers.value))), // 全数据
@@ -1300,9 +1397,9 @@ export class CanvasManager {
singleLayers.unshift({...print});
}
})
otherData_?.trims?.prints?.forEach((print, index) => {
print.name = t("Canvas.Elements") + (index + 1);
printTrimsLayers.unshift({...print});
otherData_?.trims?.prints?.forEach((trims, index) => {
trims.name = t("Canvas.Elements") + (index + 1);
printTrimsLayers.unshift({...trims});
})
await this.createPrintTrimsLayers(printTrimsLayers, singleLayers);
}
@@ -1350,7 +1447,6 @@ export class CanvasManager {
if(!color) return console.warn("颜色为空不需要添加");
if(findLayer(this.layers.value, SpecialLayerId.COLOR)) return console.warn("画布中已存在颜色图层");
console.log("==========添加颜色图层", color, this.layers.value.length)
const fixedLayerObj = this.getFixedLayerObject();
// 创建颜色图层对象
const colorRect = new fabric.Rect({
id: SpecialLayerId.COLOR,
@@ -1359,8 +1455,9 @@ export class CanvasManager {
isVisible: true,
isLocked: true,
globalCompositeOperation: BlendMode.MULTIPLY,
originColor: color,
});
// await this.setObjecCliptInfo(colorRect);
await this.setObjecCliptInfo(colorRect);
const gradientObj = palletToFill(color);
const gradient = new fabric.Gradient({
type: 'linear',
@@ -1398,24 +1495,24 @@ export class CanvasManager {
const children = [];
// 添加印花和元素图层
for(let index = 0; index < printTrimsLayers.length; index++){
let print = printTrimsLayers[index];
let item = printTrimsLayers[index];
let id = generateId("layer_image_");
let name = print.name;
let name = item.name;
let image = await new Promise(resolve => {
fabric.Image.fromURL(print.path, (fabricImage)=>{
const left = flLeft - flWidth * flScaleX / 2 + (print.location?.[0] || 0) * flScaleX
const top = flTop - flHeight * flScaleY / 2 + (print.location?.[1] || 0) * flScaleY
const scaleX = flWidth * (print.scale?.[0] || 1) / fabricImage.width * flScaleX
const scaleY = flHeight * (print.scale?.[1] || 1) / fabricImage.height * flScaleY
fabric.Image.fromURL(item.path, (fabricImage)=>{
const left = flLeft - flWidth * flScaleX / 2 + (item.location?.[0] || 0) * flScaleX
const top = flTop - flHeight * flScaleY / 2 + (item.location?.[1] || 0) * flScaleY
const scaleX = flWidth * (item.scale?.[0] || 1) / fabricImage.width * flScaleX
const scaleY = flHeight * (item.scale?.[1] || 1) / fabricImage.height * flScaleY
const {x, y} = calculateRotatedTopLeftDeg(
fabricImage.width * scaleX,
fabricImage.height * scaleY,
left,
top,
0,
print.angle || 0
item.angle || 0
)
const angle = print.angle || 0
const angle = item.angle || 0
fabricImage.set({
left: x,
top: y,
@@ -1428,6 +1525,7 @@ export class CanvasManager {
selectable: true,
hasControls: true,
hasBorders: true,
sourceData: item,
});
resolve(fabricImage);
}, { crossOrigin: "anonymous" });
@@ -1446,11 +1544,11 @@ export class CanvasManager {
};
// 添加平铺图层
for(let index = 0; index < singleLayers.length; index++){
let print = singleLayers[index];
let item = singleLayers[index];
let id = generateId("layer_image_");
let name = print.name;
let name = item.name;
let image = await new Promise(resolve => {
fabric.Image.fromURL(print.path, (fabricImage)=>{
fabric.Image.fromURL(item.path, (fabricImage)=>{
const imgElement = fabricImage.getElement();
const tcanvas = document.createElement('canvas');
tcanvas.width = imgElement.width;
@@ -1461,12 +1559,11 @@ export class CanvasManager {
resolve(tcanvas);
}, { crossOrigin: "anonymous" });
})
console.log("==========添加平铺图层", fixedLayerObj.width,image.width)
let scaleX = fixedLayerObj.width / image.width * (print.scale?.[0] || 1) / 5;
let scaleY = fixedLayerObj.height / image.height * (print.scale?.[1] || 1) / 5;
let scaleX = fixedLayerObj.width / image.width * (item.scale?.[0] || 1) / 5;
let scaleY = fixedLayerObj.height / image.height * (item.scale?.[1] || 1) / 5;
let scale = fixedLayerObj.width > fixedLayerObj.height ? scaleX : scaleY;
let left = (print.location?.[0] || 0) - image.width * scale / 2
let top = (print.location?.[1] || 0) - image.height * scale / 2
let left = (item.location?.[0] || 0) - image.width * scale / 2
let top = (item.location?.[1] || 0) - image.height * scale / 2
let rect = new fabric.Rect({
id: id,
layerId: id,
@@ -1479,13 +1576,21 @@ export class CanvasManager {
scaleY: fixedLayerObj.scaleY,
originX: fixedLayerObj.originX,
originY: fixedLayerObj.originY,
sourceData: item,
fill: new fabric.Pattern({
source: image,
repeat: "repeat",
patternTransform: createPatternTransform(scale, print.angle || 0),
patternTransform: createPatternTransform(scale, item.angle || 0),
offsetX: left, // 水平偏移
offsetY: top, // 垂直偏移
}),
fill_ : {
source: item.path,
gapX: 0,
gapY: 0,
width: image.width,
height: image.height,
}
});
this.canvas.add(rect);
let layer = createLayer({
@@ -1531,31 +1636,32 @@ export class CanvasManager {
}
/**
*
* 画布事件变更后
*/
async changeCanvas(){
const fixedLayerObj = this.getFixedLayerObject();
if(!fixedLayerObj) return console.warn("固定图层对象不存在", fixedLayerObj)
const colorObject = this.getLayerObjectById(SpecialLayerId.COLOR);
if(colorObject){
const ids = this.layerManager.getBlendModeLayerIds(SpecialLayerId.SPECIAL_GROUP);
if(ids.length === 0){
ids.unshift(SpecialLayerId.SPECIAL_GROUP);
await this.setObjecCliptInfo(colorObject);
return;
}
const base64 = await this.exportManager.exportImage({layerIdArray2: ids, isEnhanceImg: true});
if(!base64) return console.warn("导出图片失败", base64)
const canvas = await base64ToCanvas(base64, fixedLayerObj.scaleX * 2, true);
const ctx = canvas.getContext('2d');
const width = fixedLayerObj.width;
const height = fixedLayerObj.height;
const x = (canvas.width - width) / 2;
const y = (canvas.height - height) / 2;
const data = ctx.getImageData(x, y, width, height);
await this.setObjecCliptInfo(colorObject, data);
this.canvas.renderAll();
}
// const fixedLayerObj = this.getFixedLayerObject();
// if(!fixedLayerObj) return console.warn("固定图层对象不存在", fixedLayerObj)
// const colorObject = this.getLayerObjectById(SpecialLayerId.COLOR);
// if(colorObject){
// const ids = this.layerManager.getBlendModeLayerIds(SpecialLayerId.SPECIAL_GROUP);
// if(ids.length === 0){
// ids.unshift(SpecialLayerId.SPECIAL_GROUP);
// await this.setObjecCliptInfo(colorObject);
// this.canvas.renderAll();
// return;
// }
// const base64 = await this.exportManager.exportImage({layerIdArray2: ids, isEnhanceImg: true});
// if(!base64) return console.warn("导出图片失败", base64)
// const canvas = await base64ToCanvas(base64, fixedLayerObj.scaleX * 2, true);
// const ctx = canvas.getContext('2d');
// const width = fixedLayerObj.width;
// const height = fixedLayerObj.height;
// const x = (canvas.width - width) / 2;
// const y = (canvas.height - height) / 2;
// const data = ctx.getImageData(x, y, width, height);
// await this.setObjecCliptInfo(colorObject, data);
// this.canvas.renderAll();
// }
}
/**