Compare commits
12 Commits
research
...
7c14b1d831
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c14b1d831 | ||
|
|
8966b52430 | ||
|
|
5fa049f73d | ||
|
|
575445f767 | ||
|
|
f43c56236b | ||
|
|
4352f7c2f4 | ||
|
|
c6b1bdbdf1 | ||
|
|
f16aa6ea14 | ||
|
|
a25abeb527 | ||
|
|
d359cd7763 | ||
| 23085d9a9b | |||
|
|
35c6dfe29c |
@@ -55,6 +55,7 @@ commandManager.setChangeCallback((info) => {
|
|||||||
emit("undo-redo-status-changed", {
|
emit("undo-redo-status-changed", {
|
||||||
canUndo: canUndo.value,
|
canUndo: canUndo.value,
|
||||||
canRedo: canRedo.value,
|
canRedo: canRedo.value,
|
||||||
|
type: info.type,
|
||||||
commandManager,
|
commandManager,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -907,7 +907,8 @@
|
|||||||
}
|
}
|
||||||
emit("changeCanvas", commandData)
|
emit("changeCanvas", commandData)
|
||||||
canvasManager.changeCanvas()
|
canvasManager.changeCanvas()
|
||||||
if ((command.canUndo || command.canRedo) && props.enabledRedGreenMode) {
|
const type = command.type
|
||||||
|
if (props.enabledRedGreenMode && (type === "undo" || type === "redo")) {
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
try {
|
try {
|
||||||
const imageData = await canvasManager.exportImage({
|
const imageData = await canvasManager.exportImage({
|
||||||
@@ -1040,6 +1041,7 @@
|
|||||||
},
|
},
|
||||||
// 导出图片
|
// 导出图片
|
||||||
exportImage: async ({
|
exportImage: async ({
|
||||||
|
isFrontBackUpdata = false, // 更新红绿图时候需要用,直接更新红绿图
|
||||||
isContainBg = false, // 是否包含背景图层
|
isContainBg = false, // 是否包含背景图层
|
||||||
isContainFixed = false, // 是否包含固定图层
|
isContainFixed = false, // 是否包含固定图层
|
||||||
isContainFixedOther = true, // 是否包含其他固定图层--颜色图层
|
isContainFixedOther = true, // 是否包含其他固定图层--颜色图层
|
||||||
@@ -1056,6 +1058,10 @@
|
|||||||
} = {}) => {
|
} = {}) => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
canvasManager?.canvas?.discardActiveObject()
|
canvasManager?.canvas?.discardActiveObject()
|
||||||
|
if (isFrontBackUpdata) {
|
||||||
|
await canvasManager?.setSpecialCliptInfo(true, true)
|
||||||
|
canvasManager.canvas.renderAll()
|
||||||
|
}
|
||||||
var base64 = await canvasManager.exportImage({
|
var base64 = await canvasManager.exportImage({
|
||||||
isContainBg,
|
isContainBg,
|
||||||
isContainFixed,
|
isContainFixed,
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ import { getObjectAlphaToCanvas } from "../utils/objectHelper";
|
|||||||
import { AddLayerCommand, RemoveLayerCommand, ToggleChildLayerVisibilityCommand } from "../commands/LayerCommands";
|
import { AddLayerCommand, RemoveLayerCommand, ToggleChildLayerVisibilityCommand } from "../commands/LayerCommands";
|
||||||
import { fa, id } from "element-plus/es/locales.mjs";
|
import { fa, id } from "element-plus/es/locales.mjs";
|
||||||
import i18n from "@/lang/index.ts";
|
import i18n from "@/lang/index.ts";
|
||||||
const {t} = i18n.global;
|
const { t } = i18n.global;
|
||||||
|
|
||||||
export class CanvasManager {
|
export class CanvasManager {
|
||||||
constructor(canvasElement, options) {
|
constructor(canvasElement, options) {
|
||||||
@@ -70,7 +70,7 @@ export class CanvasManager {
|
|||||||
this.handleCanvasInit = null; // 画布初始化回调函数
|
this.handleCanvasInit = null; // 画布初始化回调函数
|
||||||
this.partManager = options.partManager || null;
|
this.partManager = options.partManager || null;
|
||||||
this.props = options.props || {};
|
this.props = options.props || {};
|
||||||
this.emit = options.emit || (() => {});
|
this.emit = options.emit || (() => { });
|
||||||
this.awaitCanvasRun = null;
|
this.awaitCanvasRun = null;
|
||||||
this.canvasChangeing = false;
|
this.canvasChangeing = false;
|
||||||
// 初始化画布
|
// 初始化画布
|
||||||
@@ -176,9 +176,9 @@ export class CanvasManager {
|
|||||||
// 添加笔刷图像转换处理回调
|
// 添加笔刷图像转换处理回调
|
||||||
this.canvas.onBrushImageConverted = async (fabricImage) => {
|
this.canvas.onBrushImageConverted = async (fabricImage) => {
|
||||||
const activeTool = this.toolManager?.activeTool?.value;
|
const activeTool = this.toolManager?.activeTool?.value;
|
||||||
if(activeTool === OperationType.PART_BRUSH){
|
if (activeTool === OperationType.PART_BRUSH) {
|
||||||
this.partManager?.addDrawPartImage(fabricImage);
|
this.partManager?.addDrawPartImage(fabricImage);
|
||||||
}else{
|
} else {
|
||||||
await this.addImageToLayer({ fabricImage, targetLayerId: null });
|
await this.addImageToLayer({ fabricImage, targetLayerId: null });
|
||||||
}
|
}
|
||||||
// 返回false表示使用默认行为(直接添加到画布)
|
// 返回false表示使用默认行为(直接添加到画布)
|
||||||
@@ -203,7 +203,7 @@ export class CanvasManager {
|
|||||||
// 可以在这里保存状态到命令管理器
|
// 可以在这里保存状态到命令管理器
|
||||||
const affectedObjects = e.targets || [];
|
const affectedObjects = e.targets || [];
|
||||||
const activeTool = this.toolManager?.activeTool?.value;
|
const activeTool = this.toolManager?.activeTool?.value;
|
||||||
if(activeTool === OperationType.PART_ERASER){
|
if (activeTool === OperationType.PART_ERASER) {
|
||||||
return this.partManager?.onErasingEnd(affectedObjects);
|
return this.partManager?.onErasingEnd(affectedObjects);
|
||||||
}
|
}
|
||||||
const command = this.eraserStateManager.endErasing(affectedObjects);
|
const command = this.eraserStateManager.endErasing(affectedObjects);
|
||||||
@@ -461,7 +461,7 @@ export class CanvasManager {
|
|||||||
// this.canvas.renderAll();
|
// this.canvas.renderAll();
|
||||||
}
|
}
|
||||||
// 重置画布大小参照固定图层
|
// 重置画布大小参照固定图层
|
||||||
async resetCanvasSizeByFixedLayer(){
|
async resetCanvasSizeByFixedLayer() {
|
||||||
// 重置画布大小为固定图层的大小
|
// 重置画布大小为固定图层的大小
|
||||||
const fixedLayerObj = this.getFixedLayerObject();
|
const fixedLayerObj = this.getFixedLayerObject();
|
||||||
const backgroundObject = this.getBackgroundLayerObject();
|
const backgroundObject = this.getBackgroundLayerObject();
|
||||||
@@ -475,10 +475,10 @@ export class CanvasManager {
|
|||||||
fixedLayerObj.height,
|
fixedLayerObj.height,
|
||||||
fixedLayerObj.scaleY,
|
fixedLayerObj.scaleY,
|
||||||
backgroundObject.width,
|
backgroundObject.width,
|
||||||
backgroundObject.scaleX,
|
backgroundObject.scaleX,
|
||||||
backgroundObject.height,
|
backgroundObject.height,
|
||||||
backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
backgroundObject.scaleY, 'CanvasManager resetCanvasSizeByFixedLayer')
|
||||||
if(Math.abs(fwidth/bwidth - fheight/bheight) < 0.1) return;
|
if (Math.abs(fwidth / bwidth - fheight / bheight) < 0.1) return;
|
||||||
this.canvasWidth.value = fwidth
|
this.canvasWidth.value = fwidth
|
||||||
this.canvasHeight.value = fheight
|
this.canvasHeight.value = fheight
|
||||||
backgroundObject.set({
|
backgroundObject.set({
|
||||||
@@ -489,7 +489,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
width: this.canvasWidth.value,
|
width: this.canvasWidth.value,
|
||||||
height: this.canvasHeight.value,
|
height: this.canvasHeight.value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 重置视图变换,使元素回到原始位置
|
* 重置视图变换,使元素回到原始位置
|
||||||
* @private
|
* @private
|
||||||
@@ -623,17 +623,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
this.updateMaskPosition(backgroundObject);
|
this.updateMaskPosition(backgroundObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新颜色层信息
|
this.setSpecialCliptInfo(false, true)
|
||||||
// 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({});
|
|
||||||
await this.setObjecCliptInfo(groupRect);
|
|
||||||
groupLayer.clippingMask = groupRect.toObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重新渲染画布
|
// 重新渲染画布
|
||||||
this.canvas.renderAll();
|
this.canvas.renderAll();
|
||||||
@@ -868,7 +858,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
|
|
||||||
return layerObjectByLayerId;
|
return layerObjectByLayerId;
|
||||||
}
|
}
|
||||||
getObjectsByIdOrLayerId(ids){
|
getObjectsByIdOrLayerId(ids) {
|
||||||
const objects = this.canvas.getObjects().filter((obj) => {
|
const objects = this.canvas.getObjects().filter((obj) => {
|
||||||
return ids.includes(obj.id) || ids.includes(obj.layerId);
|
return ids.includes(obj.id) || ids.includes(obj.layerId);
|
||||||
});
|
});
|
||||||
@@ -1035,16 +1025,16 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
|
|
||||||
// 处理特殊图层的显示状态
|
// 处理特殊图层的显示状态
|
||||||
const ptlids = [];
|
const ptlids = [];
|
||||||
if(!enhancedOptions.isPrintTrimsNoRepeat || !enhancedOptions.isPrintTrimsRepeat){
|
if (!enhancedOptions.isPrintTrimsNoRepeat || !enhancedOptions.isPrintTrimsRepeat) {
|
||||||
let layers = this.layers?.value?.find((layer) => layer.isPrintTrimsGroup)?.children || [];
|
let layers = this.layers?.value?.find((layer) => layer.isPrintTrimsGroup)?.children || [];
|
||||||
for(let layer of layers){
|
for (let layer of layers) {
|
||||||
if(!layer.visible) continue;
|
if (!layer.visible) continue;
|
||||||
let repeat = layer.fabricObjects?.[0]?.fill?.repeat || "no-repeat";
|
let repeat = layer.fabricObjects?.[0]?.fill?.repeat || "no-repeat";
|
||||||
if(typeof repeat !== "string") repeat = "no-repeat";
|
if (typeof repeat !== "string") repeat = "no-repeat";
|
||||||
if(repeat === "no-repeat"){
|
if (repeat === "no-repeat") {
|
||||||
if(enhancedOptions.isPrintTrimsNoRepeat) continue;
|
if (enhancedOptions.isPrintTrimsNoRepeat) continue;
|
||||||
}else{
|
} else {
|
||||||
if(enhancedOptions.isPrintTrimsRepeat) continue;
|
if (enhancedOptions.isPrintTrimsRepeat) continue;
|
||||||
}
|
}
|
||||||
ptlids.push(layer.id);
|
ptlids.push(layer.id);
|
||||||
const command = new ToggleChildLayerVisibilityCommand({
|
const command = new ToggleChildLayerVisibilityCommand({
|
||||||
@@ -1059,8 +1049,8 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
}
|
}
|
||||||
const res = await this.exportManager.exportImage(enhancedOptions);
|
const res = await this.exportManager.exportImage(enhancedOptions);
|
||||||
// 恢复特殊图层的显示状态
|
// 恢复特殊图层的显示状态
|
||||||
if(ptlids.length > 0){
|
if (ptlids.length > 0) {
|
||||||
for(let id of ptlids){
|
for (let id of ptlids) {
|
||||||
const command = new ToggleChildLayerVisibilityCommand({
|
const command = new ToggleChildLayerVisibilityCommand({
|
||||||
canvas: this.canvas,
|
canvas: this.canvas,
|
||||||
layers: this.layers,
|
layers: this.layers,
|
||||||
@@ -1086,7 +1076,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
// 导出颜色图层信息
|
// 导出颜色图层信息
|
||||||
const color = await this.exportColorLayer().catch(() => (null));
|
const color = await this.exportColorLayer().catch(() => (null));
|
||||||
// 导出印花和元素图层信息
|
// 导出印花和元素图层信息
|
||||||
const printTrimsData = await this.exportPrintTrimsLayers().catch(() => ({prints: null, trims: null}));
|
const printTrimsData = await this.exportPrintTrimsLayers().catch(() => ({ prints: null, trims: null }));
|
||||||
|
|
||||||
const obj = {
|
const obj = {
|
||||||
color,
|
color,
|
||||||
@@ -1106,7 +1096,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
return Promise.reject("颜色图层不存在");
|
return Promise.reject("颜色图层不存在");
|
||||||
}
|
}
|
||||||
const object = this.getLayerObjectById(SpecialLayerId.COLOR);
|
const object = this.getLayerObjectById(SpecialLayerId.COLOR);
|
||||||
if(!object){
|
if (!object) {
|
||||||
console.warn("颜色图层不存在,请确保已添加颜色图层");
|
console.warn("颜色图层不存在,请确保已添加颜色图层");
|
||||||
return Promise.reject("颜色图层不存在");
|
return Promise.reject("颜色图层不存在");
|
||||||
}
|
}
|
||||||
@@ -1137,7 +1127,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
});
|
});
|
||||||
canvas.clear();
|
canvas.clear();
|
||||||
const color = object.originColor;
|
const color = object.originColor;
|
||||||
return {css, base64, color};
|
return { css, base64, color };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1145,11 +1135,11 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
*/
|
*/
|
||||||
async exportPrintTrimsLayers() {
|
async exportPrintTrimsLayers() {
|
||||||
const glayer = this.layerManager.getLayerById(SpecialLayerId.SPECIAL_GROUP);
|
const glayer = this.layerManager.getLayerById(SpecialLayerId.SPECIAL_GROUP);
|
||||||
if(!glayer) return Promise.reject("印花和元素图层组不存在");
|
if (!glayer) return Promise.reject("印花和元素图层组不存在");
|
||||||
const ids = glayer.children.map((v) => v.id);
|
const ids = glayer.children.map((v) => v.id);
|
||||||
const objects = this.getObjectsByIdOrLayerId(ids);
|
const objects = this.getObjectsByIdOrLayerId(ids);
|
||||||
const fixedLayerObj = this.getFixedLayerObject();
|
const fixedLayerObj = this.getFixedLayerObject();
|
||||||
if(!fixedLayerObj) return Promise.reject("固定图层不存在");
|
if (!fixedLayerObj) return Promise.reject("固定图层不存在");
|
||||||
const flWidth = fixedLayerObj.width
|
const flWidth = fixedLayerObj.width
|
||||||
const flHeight = fixedLayerObj.height
|
const flHeight = fixedLayerObj.height
|
||||||
const flTop = fixedLayerObj.top
|
const flTop = fixedLayerObj.top
|
||||||
@@ -1161,7 +1151,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
objects.forEach((v, i) => {
|
objects.forEach((v, i) => {
|
||||||
const label = glayer.children.find((v_) => (v_.id === v.layerId || v_.id === v.id));
|
const label = glayer.children.find((v_) => (v_.id === v.layerId || v_.id === v.id));
|
||||||
const sourceData = label?.metadata?.sourceData;
|
const sourceData = label?.metadata?.sourceData;
|
||||||
if(!sourceData) return;
|
if (!sourceData) return;
|
||||||
const obj = {
|
const obj = {
|
||||||
ifSingle: typeof v.fill === "string",
|
ifSingle: typeof v.fill === "string",
|
||||||
level2Type: sourceData.level2Type,
|
level2Type: sourceData.level2Type,
|
||||||
@@ -1173,7 +1163,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
angle: v.angle,
|
angle: v.angle,
|
||||||
name: sourceData.name,
|
name: sourceData.name,
|
||||||
priority: i + 1,
|
priority: i + 1,
|
||||||
object:{
|
object: {
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
scaleX: 0,//对象的缩放比例
|
scaleX: 0,//对象的缩放比例
|
||||||
@@ -1192,8 +1182,8 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
let top = (v.top - (flTop - flHeight * flScaleY / 2));
|
let top = (v.top - (flTop - flHeight * flScaleY / 2));
|
||||||
let width = (v.width * v.scaleX);
|
let width = (v.width * v.scaleX);
|
||||||
let height = (v.height * v.scaleY);
|
let height = (v.height * v.scaleY);
|
||||||
if(v.originX === "center" && v.originY === "center") {
|
if (v.originX === "center" && v.originY === "center") {
|
||||||
let {x:cx, y:cy} = calculateTopLeftPoint(width, height, left, top, v.angle);
|
let { x: cx, y: cy } = calculateTopLeftPoint(width, height, left, top, v.angle);
|
||||||
left = cx;
|
left = cx;
|
||||||
top = cy;
|
top = cy;
|
||||||
}
|
}
|
||||||
@@ -1205,18 +1195,18 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
obj.object.left = oX;
|
obj.object.left = oX;
|
||||||
obj.object.scaleX = oScaleX;
|
obj.object.scaleX = oScaleX;
|
||||||
obj.object.scaleY = oScaleY;
|
obj.object.scaleY = oScaleY;
|
||||||
if(obj.ifSingle){
|
if (obj.ifSingle) {
|
||||||
// 单个的是从中心计算的
|
// 单个的是从中心计算的
|
||||||
let {x:cx, y:cy} = calculateCenterPoint(width, height, left, top, v.angle);
|
let { x: cx, y: cy } = calculateCenterPoint(width, height, left, top, v.angle);
|
||||||
let oX = (cx-width/2) / flScaleX;
|
let oX = (cx - width / 2) / flScaleX;
|
||||||
let oY = (cy-height/2) / flScaleY;
|
let oY = (cy - height / 2) / flScaleY;
|
||||||
obj.location = [oX, oY];
|
obj.location = [oX, oY];
|
||||||
obj.scale = [oScaleX, oScaleY];
|
obj.scale = [oScaleX, oScaleY];
|
||||||
}else{
|
} else {
|
||||||
let fill = v.fill;
|
let fill = v.fill;
|
||||||
let fill_ = v.fill_;
|
let fill_ = v.fill_;
|
||||||
if(!fill || !fill_) return console.warn("印花元素不存在fill或fill_属性");
|
if (!fill || !fill_) return console.warn("印花元素不存在fill或fill_属性");
|
||||||
let {scale, angle} = getTransformScaleAngle(fill.patternTransform);
|
let { scale, angle } = getTransformScaleAngle(fill.patternTransform);
|
||||||
let scaleX = scale * 5 * v.fill_.width / flWidth;
|
let scaleX = scale * 5 * v.fill_.width / flWidth;
|
||||||
let scaleY = scale * 5 * v.fill_.height / flHeight;
|
let scaleY = scale * 5 * v.fill_.height / flHeight;
|
||||||
let scaleXY = flWidth > flHeight ? scaleX : scaleY;
|
let scaleXY = flWidth > flHeight ? scaleX : scaleY;
|
||||||
@@ -1231,16 +1221,16 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
obj.object.gapY = fill_.gapY;
|
obj.object.gapY = fill_.gapY;
|
||||||
obj.object.fill_repeat = fill.repeat;
|
obj.object.fill_repeat = fill.repeat;
|
||||||
}
|
}
|
||||||
if(sourceData.type === "print"){
|
if (sourceData.type === "print") {
|
||||||
prints.push(obj);
|
prints.push(obj);
|
||||||
}else if(sourceData.type === "trims"){
|
} else if (sourceData.type === "trims") {
|
||||||
trims.push(obj);
|
trims.push(obj);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// prints.sort((a, b) => a.ifSingle ? 1 : -1);
|
// prints.sort((a, b) => a.ifSingle ? 1 : -1);
|
||||||
// prints.forEach((v, i) => v.priority = i + 1);
|
// prints.forEach((v, i) => v.priority = i + 1);
|
||||||
// trims.forEach((v, i) => v.priority = i + 1);
|
// trims.forEach((v, i) => v.priority = i + 1);
|
||||||
return {prints, trims};
|
return { prints, trims };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1283,7 +1273,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
// 排除颜色图层和特殊组图层
|
// 排除颜色图层和特殊组图层
|
||||||
const excludedLayers = [SpecialLayerId.COLOR, SpecialLayerId.SPECIAL_GROUP];
|
const excludedLayers = [SpecialLayerId.COLOR, SpecialLayerId.SPECIAL_GROUP];
|
||||||
this.layers.value.forEach((layer) => {
|
this.layers.value.forEach((layer) => {
|
||||||
if(excludedLayers.includes(layer.id)){
|
if (excludedLayers.includes(layer.id)) {
|
||||||
excludedLayers.push(...layer.children?.map((child) => child.id));
|
excludedLayers.push(...layer.children?.map((child) => child.id));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1465,16 +1455,16 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** 修复JSON数据中的ID丢失问题 */
|
/** 修复JSON数据中的ID丢失问题 */
|
||||||
FixJsonIdLoss(json){
|
FixJsonIdLoss(json) {
|
||||||
const layerIds = [];
|
const layerIds = [];
|
||||||
const layers = json?.layers || [];
|
const layers = json?.layers || [];
|
||||||
const objects = json?.canvas?.objects || [];
|
const objects = json?.canvas?.objects || [];
|
||||||
layers.forEach((layer) => {
|
layers.forEach((layer) => {
|
||||||
layerIds.push(layer.id);
|
layerIds.push(layer.id);
|
||||||
layer.children?.forEach((child) => layerIds.push(child.id));
|
layer.children?.forEach((child) => layerIds.push(child.id));
|
||||||
if(!layer.fabricObjects?.[0]?.id && !layer.fabricObject?.id){
|
if (!layer.fabricObjects?.[0]?.id && !layer.fabricObject?.id) {
|
||||||
const obj = objects?.find((o) => o.layerId === layer.id);
|
const obj = objects?.find((o) => o.layerId === layer.id);
|
||||||
if(obj) {
|
if (obj) {
|
||||||
layer.fabricObjects = [{
|
layer.fabricObjects = [{
|
||||||
id: obj.id,
|
id: obj.id,
|
||||||
type: obj.type,
|
type: obj.type,
|
||||||
@@ -1491,11 +1481,11 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
const excludedObjects = [SpecialLayerId.PART_SELECTOR];
|
const excludedObjects = [SpecialLayerId.PART_SELECTOR];
|
||||||
json.canvas.objects = objects.filter((v) => {
|
json.canvas.objects = objects.filter((v) => {
|
||||||
// 指定ID排除
|
// 指定ID排除
|
||||||
if(excludedObjects.includes(v.id)) return false;
|
if (excludedObjects.includes(v.id)) return false;
|
||||||
|
|
||||||
if(v.isBackground || v.isFixed) return true;
|
if (v.isBackground || v.isFixed) return true;
|
||||||
// 当前图层不存在当前对象
|
// 当前图层不存在当前对象
|
||||||
if(!layerIds.includes(v.layerId)) return false;
|
if (!layerIds.includes(v.layerId)) return false;
|
||||||
return true
|
return true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1507,22 +1497,22 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
*/
|
*/
|
||||||
async createOtherLayers(otherData) {
|
async createOtherLayers(otherData) {
|
||||||
if (!otherData) return console.warn("otherData 为空不需要添加");
|
if (!otherData) return console.warn("otherData 为空不需要添加");
|
||||||
let resolve = ()=>{};
|
let resolve = () => { };
|
||||||
this.awaitCanvasRun = ()=>(new Promise((v) => resolve = v))
|
this.awaitCanvasRun = () => (new Promise((v) => resolve = v))
|
||||||
const otherData_ = JSON.parse(JSON.stringify(otherData));
|
const otherData_ = JSON.parse(JSON.stringify(otherData));
|
||||||
console.log("==========创建其他图层", otherData_);
|
console.log("==========创建其他图层", otherData_);
|
||||||
|
|
||||||
// 删除颜色图层和特殊组图层
|
// 删除颜色图层和特殊组图层
|
||||||
const ids = [SpecialLayerId.COLOR, SpecialLayerId.SPECIAL_GROUP];
|
const ids = [SpecialLayerId.COLOR, SpecialLayerId.SPECIAL_GROUP];
|
||||||
this.layers.value = this.layers.value.filter((layer) => {
|
this.layers.value = this.layers.value.filter((layer) => {
|
||||||
if(ids.includes(layer.id)){
|
if (ids.includes(layer.id)) {
|
||||||
ids.push(...layer.children?.map((child) => child.id));
|
ids.push(...layer.children?.map((child) => child.id));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
this.canvas.getObjects().forEach((v) => {
|
this.canvas.getObjects().forEach((v) => {
|
||||||
if(ids.includes(v.id) || ids.includes(v.layerId)){
|
if (ids.includes(v.id) || ids.includes(v.layerId)) {
|
||||||
this.canvas.remove(v)
|
this.canvas.remove(v)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1536,18 +1526,18 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
otherData_.printObject?.prints?.forEach((print, index) => {// 印花
|
otherData_.printObject?.prints?.forEach((print, index) => {// 印花
|
||||||
print.name = t("Canvas.Print") + (index + 1);
|
print.name = t("Canvas.Print") + (index + 1);
|
||||||
print.type = "print";
|
print.type = "print";
|
||||||
if(print.ifSingle){
|
if (print.ifSingle) {
|
||||||
printTrimsLayers.unshift({...print});
|
printTrimsLayers.unshift({ ...print });
|
||||||
}else{
|
} else {
|
||||||
singleLayers.unshift({...print});
|
singleLayers.unshift({ ...print });
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
otherData_.trims?.prints?.forEach((trims, index) => {// 元素
|
otherData_.trims?.prints?.forEach((trims, index) => {// 元素
|
||||||
trims.name = t("Canvas.Elements") + (index + 1);
|
trims.name = t("Canvas.Elements") + (index + 1);
|
||||||
trims.type = "trims";
|
trims.type = "trims";
|
||||||
printTrimsLayers.unshift({...trims});
|
printTrimsLayers.unshift({ ...trims });
|
||||||
})
|
})
|
||||||
if(printTrimsLayers.length || singleLayers.length){
|
if (printTrimsLayers.length || singleLayers.length) {
|
||||||
await this.createPrintTrimsLayers(printTrimsLayers, singleLayers);
|
await this.createPrintTrimsLayers(printTrimsLayers, singleLayers);
|
||||||
}
|
}
|
||||||
await this.changeCanvas();
|
await this.changeCanvas();
|
||||||
@@ -1556,10 +1546,30 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
this.awaitCanvasRun = null;
|
this.awaitCanvasRun = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//设置印花元素颜色的裁剪信息
|
||||||
|
async setSpecialCliptInfo(isColor = true, isGroup = true) {
|
||||||
|
// 更新颜色层信息
|
||||||
|
if (isColor) {
|
||||||
|
const colorObject = this.getLayerObjectById(SpecialLayerId.COLOR);
|
||||||
|
if (colorObject) {
|
||||||
|
await this.setObjecCliptInfo(colorObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// 更新特殊组图层信息
|
||||||
|
if (isGroup) {
|
||||||
|
const groupLayer = this.layerManager.getLayerById(SpecialLayerId.SPECIAL_GROUP);
|
||||||
|
if (groupLayer) {
|
||||||
|
const groupRect = new fabric.Rect({});
|
||||||
|
await this.setObjecCliptInfo(groupRect);
|
||||||
|
groupLayer.clippingMask = groupRect.toObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// 设置画布对象的裁剪信息
|
// 设置画布对象的裁剪信息
|
||||||
async setObjecCliptInfo(tagObject, data){
|
async setObjecCliptInfo(tagObject, data) {
|
||||||
const fixedLayerObj = this.getFixedLayerObject();
|
const fixedLayerObj = this.getFixedLayerObject();
|
||||||
if(!fixedLayerObj) return console.warn("固定图层为空");
|
if (!fixedLayerObj) return console.warn("固定图层为空");
|
||||||
tagObject.set({
|
tagObject.set({
|
||||||
top: fixedLayerObj.top,
|
top: fixedLayerObj.top,
|
||||||
left: fixedLayerObj.left,
|
left: fixedLayerObj.left,
|
||||||
@@ -1572,7 +1582,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
});
|
});
|
||||||
var object = fixedLayerObj;
|
var object = fixedLayerObj;
|
||||||
const imageUrl = this.props.clothingImageUrl2;
|
const imageUrl = this.props.clothingImageUrl2;
|
||||||
if(imageUrl){
|
if (imageUrl) {
|
||||||
object = await new Promise((resolve, reject) => {
|
object = await new Promise((resolve, reject) => {
|
||||||
fabric.Image.fromURL(imageUrl, (imgObject) => {
|
fabric.Image.fromURL(imageUrl, (imgObject) => {
|
||||||
tagObject.set({
|
tagObject.set({
|
||||||
@@ -1592,8 +1602,8 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
});
|
});
|
||||||
tagObject.set('clipPath', transparentMask);
|
tagObject.set('clipPath', transparentMask);
|
||||||
}
|
}
|
||||||
async createColorLayer(color_){
|
async createColorLayer(color_) {
|
||||||
const color = color_ || {r:0,g:0,b:0,a:0};
|
const color = color_ || { r: 0, g: 0, b: 0, a: 0 };
|
||||||
// if(findLayer(this.layers.value, SpecialLayerId.COLOR)) {
|
// if(findLayer(this.layers.value, SpecialLayerId.COLOR)) {
|
||||||
// return console.warn("画布中已存在颜色图层");
|
// return console.warn("画布中已存在颜色图层");
|
||||||
// }
|
// }
|
||||||
@@ -1637,7 +1647,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 创建印花和元素图层
|
// 创建印花和元素图层
|
||||||
async createPrintTrimsLayers(printTrimsLayers, singleLayers){
|
async createPrintTrimsLayers(printTrimsLayers, singleLayers) {
|
||||||
// if(findLayer(this.layers.value, SpecialLayerId.SPECIAL_GROUP)) {
|
// if(findLayer(this.layers.value, SpecialLayerId.SPECIAL_GROUP)) {
|
||||||
// return console.warn("画布中已存在印花和元素组图层");
|
// return console.warn("画布中已存在印花和元素组图层");
|
||||||
// }
|
// }
|
||||||
@@ -1651,12 +1661,12 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
const flScaleY = fixedLayerObj.scaleY
|
const flScaleY = fixedLayerObj.scaleY
|
||||||
const children = [];
|
const children = [];
|
||||||
// 添加印花和元素图层
|
// 添加印花和元素图层
|
||||||
for(let index = 0; index < printTrimsLayers.length; index++){
|
for (let index = 0; index < printTrimsLayers.length; index++) {
|
||||||
let item = printTrimsLayers[index];
|
let item = printTrimsLayers[index];
|
||||||
let id = generateId("layer_image_");
|
let id = generateId("layer_image_");
|
||||||
let name = item.name;
|
let name = item.name;
|
||||||
let image = await new Promise(resolve => {
|
let image = await new Promise(resolve => {
|
||||||
fabric.Image.fromURL(item.path, (fabricImage)=>{
|
fabric.Image.fromURL(item.path, (fabricImage) => {
|
||||||
resolve(fabricImage);
|
resolve(fabricImage);
|
||||||
}, { crossOrigin: "anonymous" });
|
}, { crossOrigin: "anonymous" });
|
||||||
})
|
})
|
||||||
@@ -1664,7 +1674,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
let top = flTop - flHeight * flScaleY / 2 + (item.location?.[1] || 0) * flScaleY
|
let top = flTop - flHeight * flScaleY / 2 + (item.location?.[1] || 0) * flScaleY
|
||||||
let scaleX = flWidth * (item.scale?.[0] || 1) / image.width * flScaleX
|
let scaleX = flWidth * (item.scale?.[0] || 1) / image.width * flScaleX
|
||||||
let scaleY = flHeight * (item.scale?.[1] || 1) / image.height * flScaleY
|
let scaleY = flHeight * (item.scale?.[1] || 1) / image.height * flScaleY
|
||||||
let {x, y} = calculateRotatedTopLeftDeg(
|
let { x, y } = calculateRotatedTopLeftDeg(
|
||||||
image.width * scaleX,
|
image.width * scaleX,
|
||||||
image.height * scaleY,
|
image.height * scaleY,
|
||||||
left,
|
left,
|
||||||
@@ -1679,11 +1689,11 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
let flipY = false;
|
let flipY = false;
|
||||||
let blendMode = BlendMode.NORMAL;
|
let blendMode = BlendMode.NORMAL;
|
||||||
// if(item.type === "trims") blendMode = BlendMode.NORMAL;// 元素正常
|
// if(item.type === "trims") blendMode = BlendMode.NORMAL;// 元素正常
|
||||||
if(item.object){
|
if (item.object) {
|
||||||
opacity = item.object.opacity
|
opacity = item.object.opacity
|
||||||
flipX = item.object.flipX
|
flipX = item.object.flipX
|
||||||
flipY = item.object.flipY
|
flipY = item.object.flipY
|
||||||
if(item.object.blendMode) blendMode = item.object.blendMode;
|
if (item.object.blendMode) blendMode = item.object.blendMode;
|
||||||
}
|
}
|
||||||
image.set({
|
image.set({
|
||||||
left: x,
|
left: x,
|
||||||
@@ -1714,18 +1724,18 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
isPrintTrims: true,
|
isPrintTrims: true,
|
||||||
blendMode: blendMode,
|
blendMode: blendMode,
|
||||||
fabricObjects: [image.toObject(["id", "layerId", "layerName"])],
|
fabricObjects: [image.toObject(["id", "layerId", "layerName"])],
|
||||||
metadata: {sourceData: item},
|
metadata: { sourceData: item },
|
||||||
object: image,
|
object: image,
|
||||||
})
|
})
|
||||||
children.push(layer);
|
children.push(layer);
|
||||||
};
|
};
|
||||||
// 添加平铺图层
|
// 添加平铺图层
|
||||||
for(let index = 0; index < singleLayers.length; index++){
|
for (let index = 0; index < singleLayers.length; index++) {
|
||||||
let item = singleLayers[index];
|
let item = singleLayers[index];
|
||||||
let id = generateId("layer_image_");
|
let id = generateId("layer_image_");
|
||||||
let name = item.name;
|
let name = item.name;
|
||||||
let image = await new Promise(resolve => {
|
let image = await new Promise(resolve => {
|
||||||
fabric.Image.fromURL(item.path, (fabricImage)=>{
|
fabric.Image.fromURL(item.path, (fabricImage) => {
|
||||||
const imgElement = fabricImage.getElement();
|
const imgElement = fabricImage.getElement();
|
||||||
const tcanvas = document.createElement('canvas');
|
const tcanvas = document.createElement('canvas');
|
||||||
tcanvas.width = imgElement.width;
|
tcanvas.width = imgElement.width;
|
||||||
@@ -1754,7 +1764,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
let flipY = false;
|
let flipY = false;
|
||||||
let blendMode = BlendMode.NORMAL;
|
let blendMode = BlendMode.NORMAL;
|
||||||
let fill_repeat = "repeat"
|
let fill_repeat = "repeat"
|
||||||
if(item.object){
|
if (item.object) {
|
||||||
top += item.object.top * flScaleY
|
top += item.object.top * flScaleY
|
||||||
left += item.object.left * flScaleX
|
left += item.object.left * flScaleX
|
||||||
scaleX *= item.object.scaleX
|
scaleX *= item.object.scaleX
|
||||||
@@ -1763,11 +1773,11 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
angle = item.object.angle
|
angle = item.object.angle
|
||||||
flipX = item.object.flipX
|
flipX = item.object.flipX
|
||||||
flipY = item.object.flipY
|
flipY = item.object.flipY
|
||||||
if(item.object.blendMode) blendMode = item.object.blendMode;
|
if (item.object.blendMode) blendMode = item.object.blendMode;
|
||||||
gapX = item.object.gapX
|
gapX = item.object.gapX
|
||||||
gapY = item.object.gapY
|
gapY = item.object.gapY
|
||||||
fillSource = imageAddGapToCanvas(image, gapX, gapY);
|
fillSource = imageAddGapToCanvas(image, gapX, gapY);
|
||||||
if(item.object.fill_repeat) fill_repeat = item.object.fill_repeat;
|
if (item.object.fill_repeat) fill_repeat = item.object.fill_repeat;
|
||||||
}
|
}
|
||||||
let rect = new fabric.Rect({
|
let rect = new fabric.Rect({
|
||||||
id: id,
|
id: id,
|
||||||
@@ -1791,7 +1801,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
offsetX: offsetX, // 水平偏移
|
offsetX: offsetX, // 水平偏移
|
||||||
offsetY: offsetY, // 垂直偏移
|
offsetY: offsetY, // 垂直偏移
|
||||||
}),
|
}),
|
||||||
fill_ : {
|
fill_: {
|
||||||
source: item.path,
|
source: item.path,
|
||||||
gapX: gapX,
|
gapX: gapX,
|
||||||
gapY: gapY,
|
gapY: gapY,
|
||||||
@@ -1811,7 +1821,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
isPrintTrims: true,
|
isPrintTrims: true,
|
||||||
blendMode: blendMode,
|
blendMode: blendMode,
|
||||||
fabricObjects: [rect.toObject(["id", "layerId", "layerName"])],
|
fabricObjects: [rect.toObject(["id", "layerId", "layerName"])],
|
||||||
metadata: {sourceData: item},
|
metadata: { sourceData: item },
|
||||||
object: rect,
|
object: rect,
|
||||||
})
|
})
|
||||||
children.push(layer);
|
children.push(layer);
|
||||||
@@ -1828,9 +1838,9 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
// })
|
// })
|
||||||
// children.push(layer);
|
// children.push(layer);
|
||||||
// }
|
// }
|
||||||
if(children.length === 0) return;
|
if (children.length === 0) return;
|
||||||
// 印花元素排序
|
// 印花元素排序
|
||||||
if(new Set(children.map(v => v.metadata.sourceData.priority)).size === children.length){
|
if (new Set(children.map(v => v.metadata.sourceData.priority)).size === children.length) {
|
||||||
children.sort((a, b) => b.metadata.sourceData.priority - a.metadata.sourceData.priority);
|
children.sort((a, b) => b.metadata.sourceData.priority - a.metadata.sourceData.priority);
|
||||||
}
|
}
|
||||||
children.forEach(layer => {
|
children.forEach(layer => {
|
||||||
@@ -1858,21 +1868,21 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
/**
|
/**
|
||||||
* 画布事件变更后
|
* 画布事件变更后
|
||||||
*/
|
*/
|
||||||
async changeCanvas(fids = [], isBeforeChange = false){
|
async changeCanvas(fids = [], isBeforeChange = false) {
|
||||||
if(!isBeforeChange) this.canvasChangeing = false;
|
if (!isBeforeChange) this.canvasChangeing = false;
|
||||||
const fixedLayerObj = this.getFixedLayerObject();
|
const fixedLayerObj = this.getFixedLayerObject();
|
||||||
if(!fixedLayerObj) return console.warn("固定图层对象不存在", fixedLayerObj)
|
if (!fixedLayerObj) return console.warn("固定图层对象不存在", fixedLayerObj)
|
||||||
const colorObject = this.getLayerObjectById(SpecialLayerId.COLOR);
|
const colorObject = this.getLayerObjectById(SpecialLayerId.COLOR);
|
||||||
if(colorObject){
|
if (colorObject) {
|
||||||
const ids = this.layerManager.getBlendModeLayerIds(SpecialLayerId.SPECIAL_GROUP).filter(id => !fids.includes(id));
|
const ids = this.layerManager.getBlendModeLayerIds(SpecialLayerId.SPECIAL_GROUP).filter(id => !fids.includes(id));
|
||||||
if(ids.length === 0){
|
if (ids.length === 0) {
|
||||||
ids.unshift(SpecialLayerId.SPECIAL_GROUP);
|
ids.unshift(SpecialLayerId.SPECIAL_GROUP);
|
||||||
await this.setObjecCliptInfo(colorObject);
|
await this.setObjecCliptInfo(colorObject);
|
||||||
this.canvas.renderAll();
|
this.canvas.renderAll();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const base64 = await this.exportManager.exportImage({layerIdArray2: ids, isEnhanceImg: true});
|
const base64 = await this.exportManager.exportImage({ layerIdArray2: ids, isEnhanceImg: true });
|
||||||
if(!base64) return console.warn("导出图片失败", base64)
|
if (!base64) return console.warn("导出图片失败", base64)
|
||||||
const canvas = await base64ToCanvas(base64, fixedLayerObj.scaleX * 2, true);
|
const canvas = await base64ToCanvas(base64, fixedLayerObj.scaleX * 2, true);
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
const width = fixedLayerObj.width;
|
const width = fixedLayerObj.width;
|
||||||
@@ -1885,15 +1895,15 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** 画布变更之前 */
|
/** 画布变更之前 */
|
||||||
async beforeChangeCanvas(objects){
|
async beforeChangeCanvas(objects) {
|
||||||
if(this.canvasChangeing) return;
|
if (this.canvasChangeing) return;
|
||||||
const ids = objects.filter(v => {
|
const ids = objects.filter(v => {
|
||||||
return v.isPrintTrims && v.globalCompositeOperation && v.globalCompositeOperation !== BlendMode.NORMAL
|
return v.isPrintTrims && v.globalCompositeOperation && v.globalCompositeOperation !== BlendMode.NORMAL
|
||||||
}).map(v => v.layerId);
|
}).map(v => v.layerId);
|
||||||
if(ids.length > 0){
|
if (ids.length > 0) {
|
||||||
this.canvasChangeing = true;
|
this.canvasChangeing = true;
|
||||||
this.canvas.getObjects().forEach(v => {
|
this.canvas.getObjects().forEach(v => {
|
||||||
if(ids.includes(v.layerId)){
|
if (ids.includes(v.layerId)) {
|
||||||
v.globalCompositeOperation_ = v.globalCompositeOperation;
|
v.globalCompositeOperation_ = v.globalCompositeOperation;
|
||||||
v.globalCompositeOperation = BlendMode.NORMAL;
|
v.globalCompositeOperation = BlendMode.NORMAL;
|
||||||
}
|
}
|
||||||
@@ -2103,13 +2113,13 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
moveActiveObject(direction, step = 1) {
|
moveActiveObject(direction, step = 1) {
|
||||||
const objects = [];
|
const objects = [];
|
||||||
const activeObject = this.canvas.getActiveObject();
|
const activeObject = this.canvas.getActiveObject();
|
||||||
if(!activeObject) return;
|
if (!activeObject) return;
|
||||||
const initPos = {
|
const initPos = {
|
||||||
id: activeObject.id,
|
id: activeObject.id,
|
||||||
left: activeObject.left,
|
left: activeObject.left,
|
||||||
top: activeObject.top,
|
top: activeObject.top,
|
||||||
};
|
};
|
||||||
switch(direction) {
|
switch (direction) {
|
||||||
case "up":
|
case "up":
|
||||||
activeObject.top -= step;
|
activeObject.top -= step;
|
||||||
break;
|
break;
|
||||||
@@ -2123,7 +2133,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
|||||||
activeObject.left += step;
|
activeObject.left += step;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!activeObject.id) return this.canvas.renderAll();
|
if (!activeObject.id) return this.canvas.renderAll();
|
||||||
const cmd = new ObjectMoveCommand({
|
const cmd = new ObjectMoveCommand({
|
||||||
canvas: this.canvas,
|
canvas: this.canvas,
|
||||||
initPos,
|
initPos,
|
||||||
|
|||||||
@@ -606,7 +606,9 @@ export class ExportManager {
|
|||||||
imageSmoothingEnabled: true,
|
imageSmoothingEnabled: true,
|
||||||
});
|
});
|
||||||
// tempFabricCanvas.setZoom(1);
|
// tempFabricCanvas.setZoom(1);
|
||||||
console.log("==========", fixedLayerObject)
|
const ox = fixedLayerObject.left - fixedLayerObject.width * fixedLayerObject.scaleX / 2
|
||||||
|
const oy = fixedLayerObject.top - fixedLayerObject.height * fixedLayerObject.scaleY / 2
|
||||||
|
// console.log("==========", fixedLayerObject, ox, oy)
|
||||||
try {
|
try {
|
||||||
// 克隆并添加所有对象到临时画布,需要调整位置相对于固定图层
|
// 克隆并添加所有对象到临时画布,需要调整位置相对于固定图层
|
||||||
for (let i = 0; i < objectsToExport.length; i++) {
|
for (let i = 0; i < objectsToExport.length; i++) {
|
||||||
@@ -616,15 +618,20 @@ export class ExportManager {
|
|||||||
restoreOpacityInRedGreen && true
|
restoreOpacityInRedGreen && true
|
||||||
);
|
);
|
||||||
if (cloned) {
|
if (cloned) {
|
||||||
|
let scaleX = cloned.scaleX / fixedLayerObject.scaleX
|
||||||
|
let scaleY = cloned.scaleY / fixedLayerObject.scaleY
|
||||||
|
let top = (cloned.top - oy) * scaleY
|
||||||
|
let left = (cloned.left - ox) * scaleX
|
||||||
|
if (cloned.originX === "center" && cloned.originY === "center") {
|
||||||
|
top = canvasHeight / 2
|
||||||
|
left = canvasWidth / 2
|
||||||
|
}
|
||||||
cloned.set({
|
cloned.set({
|
||||||
left: canvasWidth / 2,
|
left: left,
|
||||||
top: canvasHeight / 2,
|
top: top,
|
||||||
scaleX: cloned.scaleX / fixedLayerObject.scaleX,
|
scaleX: scaleX,
|
||||||
scaleY: cloned.scaleY / fixedLayerObject.scaleY,
|
scaleY: scaleY,
|
||||||
originX: "center",
|
|
||||||
originY: "center",
|
|
||||||
});
|
});
|
||||||
console.log("==========", {...cloned})
|
|
||||||
// 更新对象坐标
|
// 更新对象坐标
|
||||||
cloned.setCoords();
|
cloned.setCoords();
|
||||||
tempFabricCanvas.add(cloned);
|
tempFabricCanvas.add(cloned);
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ export class CommandManager {
|
|||||||
this._recordPerformance("execute", command.constructor.name, duration);
|
this._recordPerformance("execute", command.constructor.name, duration);
|
||||||
|
|
||||||
// 通知状态变化
|
// 通知状态变化
|
||||||
this._notifyStateChange();
|
this._notifyStateChange("execute");
|
||||||
|
|
||||||
console.log(`✅ 命令执行成功: ${command.constructor.name}`);
|
console.log(`✅ 命令执行成功: ${command.constructor.name}`);
|
||||||
return result;
|
return result;
|
||||||
@@ -219,7 +219,7 @@ export class CommandManager {
|
|||||||
this._recordPerformance("undo", command.constructor.name, duration);
|
this._recordPerformance("undo", command.constructor.name, duration);
|
||||||
|
|
||||||
// 通知状态变化
|
// 通知状态变化
|
||||||
this._notifyStateChange();
|
this._notifyStateChange("undo");
|
||||||
|
|
||||||
console.log(`✅ 命令撤销成功: ${command.constructor.name}`);
|
console.log(`✅ 命令撤销成功: ${command.constructor.name}`);
|
||||||
return result;
|
return result;
|
||||||
@@ -258,7 +258,7 @@ export class CommandManager {
|
|||||||
this._recordPerformance("redo", command.constructor.name, duration);
|
this._recordPerformance("redo", command.constructor.name, duration);
|
||||||
|
|
||||||
// 通知状态变化
|
// 通知状态变化
|
||||||
this._notifyStateChange();
|
this._notifyStateChange("redo");
|
||||||
|
|
||||||
console.log(`✅ 命令重做成功: ${command.constructor.name}`);
|
console.log(`✅ 命令重做成功: ${command.constructor.name}`);
|
||||||
return result;
|
return result;
|
||||||
@@ -298,7 +298,7 @@ export class CommandManager {
|
|||||||
|
|
||||||
this.undoStack = [];
|
this.undoStack = [];
|
||||||
this.redoStack = [];
|
this.redoStack = [];
|
||||||
this._notifyStateChange();
|
this._notifyStateChange("clear");
|
||||||
// console.log("📝 命令历史已清空");
|
// console.log("📝 命令历史已清空");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,10 +417,12 @@ export class CommandManager {
|
|||||||
* 通知状态变化
|
* 通知状态变化
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_notifyStateChange() {
|
_notifyStateChange(type) {
|
||||||
if (this.onStateChange) {
|
if (this.onStateChange) {
|
||||||
try {
|
try {
|
||||||
this.onStateChange(this.getState());
|
const obj = this.getState();
|
||||||
|
obj.type = type;
|
||||||
|
this.onStateChange(obj);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("状态变化回调执行失败:", error);
|
console.error("状态变化回调执行失败:", error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ export class LiquifyRealTimeUpdater {
|
|||||||
|
|
||||||
if (isDrawing && this.config.useDirectUpdate) {
|
if (isDrawing && this.config.useDirectUpdate) {
|
||||||
// 拖拽过程中使用快速更新(降低质量以提高性能)
|
// 拖拽过程中使用快速更新(降低质量以提高性能)
|
||||||
this._fastUpdate(imageData);
|
await this._fastUpdate(imageData);
|
||||||
} else {
|
} else {
|
||||||
// 拖拽结束后使用完整更新(最高质量)
|
// 拖拽结束后使用完整更新(最高质量)
|
||||||
await this._fullUpdate(imageData);
|
await this._fullUpdate(imageData);
|
||||||
@@ -124,7 +124,7 @@ export class LiquifyRealTimeUpdater {
|
|||||||
* @param {ImageData} imageData 图像数据
|
* @param {ImageData} imageData 图像数据
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_fastUpdate(imageData) {
|
async _fastUpdate(imageData) {
|
||||||
if (!this.targetObject || !this.targetObject._element) {
|
if (!this.targetObject || !this.targetObject._element) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -138,12 +138,14 @@ export class LiquifyRealTimeUpdater {
|
|||||||
|
|
||||||
// 直接更新fabric对象的图像源(使用PNG格式保持质量)
|
// 直接更新fabric对象的图像源(使用PNG格式保持质量)
|
||||||
const targetElement = this.targetObject._element;
|
const targetElement = this.targetObject._element;
|
||||||
|
|
||||||
// 方案1: 直接设置src属性(最高性能)
|
// 方案1: 直接设置src属性(最高性能)
|
||||||
const dataURL = this.tempCanvas.toDataURL("image/png", quality);
|
const dataURL = this.tempCanvas.toDataURL("image/png", quality);
|
||||||
|
|
||||||
if (targetElement.src !== dataURL) {
|
if (targetElement.src !== dataURL) {
|
||||||
targetElement.src = dataURL;
|
// targetElement.src = dataURL;
|
||||||
|
const image = new Image();
|
||||||
|
image.src = dataURL;
|
||||||
|
await image.decode();
|
||||||
|
this.targetObject.setElement(image);
|
||||||
|
|
||||||
// 关键优化:直接设置fabric对象为脏状态,但不立即渲染
|
// 关键优化:直接设置fabric对象为脏状态,但不立即渲染
|
||||||
// this.targetObject.dirty = false; // 标记为不需要立即渲染
|
// this.targetObject.dirty = false; // 标记为不需要立即渲染
|
||||||
|
|||||||
@@ -447,6 +447,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</CanvasEditor>
|
</CanvasEditor>
|
||||||
</div>
|
</div>
|
||||||
|
<img src="" alt="" id="canvas-test-dom">
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style>
|
<style>
|
||||||
@@ -458,6 +459,13 @@
|
|||||||
height: 600px !important;
|
height: 600px !important;
|
||||||
z-index: 99999999;
|
z-index: 99999999;
|
||||||
}
|
}
|
||||||
|
#canvas-test-dom{
|
||||||
|
position: fixed;
|
||||||
|
z-index: 9999999999;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
* {
|
* {
|
||||||
|
|||||||
@@ -163,7 +163,6 @@ export default defineComponent({
|
|||||||
const privewDetail = async (oldSelectDetail = detailData.selectDetail)=>{
|
const privewDetail = async (oldSelectDetail = detailData.selectDetail)=>{
|
||||||
// if(!detailDom.editCanvas)return
|
// if(!detailDom.editCanvas)return
|
||||||
return new Promise(async (res,reject)=>{
|
return new Promise(async (res,reject)=>{
|
||||||
console.log(detailDom.editCanvas)
|
|
||||||
await detailDom.editCanvas.exportImage({
|
await detailDom.editCanvas.exportImage({
|
||||||
isContainFixed:true,
|
isContainFixed:true,
|
||||||
width:props.sketchSize.width,
|
width:props.sketchSize.width,
|
||||||
@@ -245,17 +244,27 @@ export default defineComponent({
|
|||||||
|
|
||||||
|
|
||||||
const frontBackChange = async (value:any)=>{
|
const frontBackChange = async (value:any)=>{
|
||||||
|
let front = detailData.frontBack.front[detailData.imgDomIndex]
|
||||||
|
let back = detailData.frontBack.back[detailData.imgDomIndex]
|
||||||
|
store.commit('DesignDetail/updataDetailItem',{maskUrl:value})
|
||||||
|
await nextTick()
|
||||||
if(!detailData.selectDetail.partialDesign.partialDesignPath && !detailData.selectDetail.partialDesign.partialDesignBase64){
|
if(!detailData.selectDetail.partialDesign.partialDesignPath && !detailData.selectDetail.partialDesign.partialDesignBase64){
|
||||||
await privewDetail()
|
await privewDetail()
|
||||||
|
}else{
|
||||||
|
await detailDom.editCanvas.exportImage({
|
||||||
|
isFrontBackUpdata: true,
|
||||||
|
isContainFixed:true,
|
||||||
|
width:props.sketchSize.width,
|
||||||
|
height:props.sketchSize.height,
|
||||||
|
}).then((rv)=>{
|
||||||
|
if(detailData.selectDetail?.partialDesign)detailData.selectDetail.partialDesign.partialDesignBase64 = rv
|
||||||
|
})
|
||||||
}
|
}
|
||||||
let full = detailData.selectDetail.partialDesign.partialDesignBase64 || detailData.selectDetail.partialDesign.partialDesignPath || detailData.selectDetail.path
|
let full = detailData.selectDetail.partialDesign.partialDesignBase64 || detailData.selectDetail.partialDesign.partialDesignPath || detailData.selectDetail.path
|
||||||
let size = {
|
let size = {
|
||||||
...detailData.canvasConfig,
|
...detailData.canvasConfig,
|
||||||
}
|
}
|
||||||
store.commit('DesignDetail/updataDetailItem',{maskUrl:value})
|
|
||||||
segmentImage(value,full,size).then(async (rv)=>{
|
segmentImage(value,full,size).then(async (rv)=>{
|
||||||
let front = detailData.frontBack.front[detailData.imgDomIndex]
|
|
||||||
let back = detailData.frontBack.back[detailData.imgDomIndex]
|
|
||||||
if(!front?.oldImageUrl)front.oldImageUrl = front.imageUrl
|
if(!front?.oldImageUrl)front.oldImageUrl = front.imageUrl
|
||||||
if(!front?.oldMaskUrl)front.oldMaskUrl = front.maskUrl
|
if(!front?.oldMaskUrl)front.oldMaskUrl = front.maskUrl
|
||||||
if(!back?.oldImageUrl)back.oldImageUrl = back.imageUrl
|
if(!back?.oldImageUrl)back.oldImageUrl = back.imageUrl
|
||||||
@@ -267,7 +276,6 @@ export default defineComponent({
|
|||||||
back.imageUrl = rv.targetBackUrl
|
back.imageUrl = rv.targetBackUrl
|
||||||
// store.commit('DesignDetail/updataDetailItem',{maskUrl:value})
|
// store.commit('DesignDetail/updataDetailItem',{maskUrl:value})
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
const editSketchCanvasInit = async (value:any)=>{
|
const editSketchCanvasInit = async (value:any)=>{
|
||||||
detailData.canvasInstance = value
|
detailData.canvasInstance = value
|
||||||
|
|||||||
@@ -393,8 +393,8 @@ export default defineComponent({
|
|||||||
angle: 0,
|
angle: 0,
|
||||||
flipX: false,
|
flipX: false,
|
||||||
flipY: false,
|
flipY: false,
|
||||||
// blendMode: "multiply",
|
blendMode: "multiply",
|
||||||
blendMode: "source-over",
|
// blendMode: "source-over",
|
||||||
gapX: 0,
|
gapX: 0,
|
||||||
gapY: 0,
|
gapY: 0,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -531,7 +531,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
const setSpeed = (item: any) => {
|
const setSpeed = (item: any) => {
|
||||||
speed.speedData = item
|
speed.speedData = {...item}
|
||||||
}
|
}
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.msg == 'Sketchboard') {
|
if (props.msg == 'Sketchboard') {
|
||||||
|
|||||||
@@ -205,7 +205,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="payment">
|
<div class="payment">
|
||||||
<div class="allocation">
|
<div class="allocation">
|
||||||
<div class="selectType">
|
<!-- <div class="selectType">
|
||||||
<div class="text">{{ $t('Renew.Payment') }}:</div>
|
<div class="text">{{ $t('Renew.Payment') }}:</div>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
@@ -227,7 +227,7 @@
|
|||||||
/>
|
/>
|
||||||
{{ $t('Renew.Alipay') }}
|
{{ $t('Renew.Alipay') }}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="gallery_btn gallery_btn_radius" @click="payment">
|
<div class="gallery_btn gallery_btn_radius" @click="payment">
|
||||||
{{ $t('upgradePlan.Continue') }}
|
{{ $t('upgradePlan.Continue') }}
|
||||||
|
|||||||
@@ -77,17 +77,10 @@ export default defineComponent({
|
|||||||
left: 50%;
|
left: 50%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translate(-50%,-50%);
|
transform: translate(-50%,-50%);
|
||||||
width: 80%;
|
|
||||||
height: auto;
|
|
||||||
max-height: 80vh;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: max-content;
|
|
||||||
video{
|
video{
|
||||||
width: 100%;
|
max-height:80vh;
|
||||||
max-height: 80vh;
|
max-width:80vw;
|
||||||
height: 100%;
|
|
||||||
object-fit: contain;
|
|
||||||
width: max-content;
|
|
||||||
}
|
}
|
||||||
.general_video_btn{
|
.general_video_btn{
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|||||||
@@ -41,10 +41,10 @@
|
|||||||
<div class="center">{{ selectObject?.styleName?selectObject?.styleName:$t('Header.All') }}</div>
|
<div class="center">{{ selectObject?.styleName?selectObject?.styleName:$t('Header.All') }}</div>
|
||||||
<div class="gallery_btn" @click="setStyle">{{ $t('Habit.Select') }}</div>
|
<div class="gallery_btn" @click="setStyle">{{ $t('Habit.Select') }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="style brand marginBottom">
|
<!-- <div class="style brand marginBottom">
|
||||||
<div class="text">{{$t('Habit.Brand')}}:</div>
|
<div class="text">{{$t('Habit.Brand')}}:</div>
|
||||||
<div class="gallery_btn" @click="setBrandDNA">{{ $t('Habit.Select') }}</div>
|
<div class="gallery_btn" @click="setBrandDNA">{{ $t('Habit.Select') }}</div>
|
||||||
</div>
|
</div> -->
|
||||||
<div class="brandImg" v-if="selectObject.userBrandDna"><img :src="selectObject.userBrandDnaImg"></div>
|
<div class="brandImg" v-if="selectObject.userBrandDna"><img :src="selectObject.userBrandDnaImg"></div>
|
||||||
<div class="brandDNAStrenght marginBottom" v-if="selectObject.userBrandDna">
|
<div class="brandDNAStrenght marginBottom" v-if="selectObject.userBrandDna">
|
||||||
<div class="text" style="font-size: 1.6rem;">
|
<div class="text" style="font-size: 1.6rem;">
|
||||||
|
|||||||
@@ -340,12 +340,12 @@ const navTypeList = (t)=>{
|
|||||||
value:'Models',
|
value:'Models',
|
||||||
router:'library=Models'
|
router:'library=Models'
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
icon:'fi-ss-gem',
|
// icon:'fi-ss-gem',
|
||||||
label:t('LibraryPage.brandDNA'),
|
// label:t('LibraryPage.brandDNA'),
|
||||||
value:'MyBrand',
|
// value:'MyBrand',
|
||||||
router:'library=MyBrand'
|
// router:'library=MyBrand'
|
||||||
},
|
// },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
// history:{
|
// history:{
|
||||||
|
|||||||
Reference in New Issue
Block a user