diff --git a/src/component/Canvas/CanvasEditor/index.vue b/src/component/Canvas/CanvasEditor/index.vue index 92e7ab71..6f98c5b8 100644 --- a/src/component/Canvas/CanvasEditor/index.vue +++ b/src/component/Canvas/CanvasEditor/index.vue @@ -977,6 +977,17 @@ defineExpose({ ...opts, }); }, + updateOtherLayers: async (otherData) => { + await canvasManager?.createOtherLayers?.(otherData, true); + layerManager.activeLayerId.value = "" + layerManager?.sortLayers(); + await layerManager?.updateLayersObjectsInteractivity?.(true); + canvasManager?.canvas?.renderAll(); + setTimeout(() => { + canvasManager.updateAllThumbnails(); + }, 500); + return true; + }, //图片url或者base64 addImageToLayer: async ( url, diff --git a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js index d5e8b9de..6a9ef705 100644 --- a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js +++ b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js @@ -1325,12 +1325,12 @@ export class CanvasManager { // } // 重载代码后支持回调中操作一些内容 - await calllBack?.(); // 确保所有对象的交互性正确设置 await this.layerManager?.updateLayersObjectsInteractivity?.(); console.log(this.layerManager.layers.value); + await calllBack?.(); // 更新所有缩略图 setTimeout(() => { this.updateAllThumbnails(); @@ -1357,13 +1357,22 @@ export class CanvasManager { * 创建其他图层:印花、颜色、元素... * @param {Object} otherData - 其他图层数据 */ - async createOtherLayers(otherData) { + async createOtherLayers(otherData, isUpdate = false) { if (!otherData) return console.warn("otherData 为空不需要添加"); const otherData_ = JSON.parse(JSON.stringify(otherData)); console.log("==========创建其他图层", otherData_); + const updateColor = !!otherData_.color; + const updateSpecialGroup = !!otherData_.printObject || !!otherData_.trims; // 删除颜色图层和特殊组图层 - const ids = [SpecialLayerId.COLOR, SpecialLayerId.SPECIAL_GROUP]; + const ids = []; + if(isUpdate){ + updateColor && ids.push(SpecialLayerId.COLOR) + updateSpecialGroup && ids.push(SpecialLayerId.SPECIAL_GROUP) + }else{ + ids.push(SpecialLayerId.COLOR) + ids.push(SpecialLayerId.SPECIAL_GROUP) + } this.layers.value = this.layers.value.filter((layer) => { if(ids.includes(layer.id)){ ids.push(...layer.children?.map((child) => child.id)); @@ -1375,11 +1384,11 @@ export class CanvasManager { // 创建颜色图层 - await this.createColorLayer(otherData_.color); + otherData_.color && await this.createColorLayer(otherData_.color); const printTrimsLayers = [];// 印花和元素图层 const singleLayers = [];// 平铺图层 - otherData_?.printObject?.prints?.forEach((print, index) => { + otherData_.printObject?.prints?.forEach((print, index) => { print.name = t("Canvas.Print") + (index + 1); if(print.ifSingle){ printTrimsLayers.unshift({...print}); @@ -1387,12 +1396,13 @@ export class CanvasManager { singleLayers.unshift({...print}); } }) - otherData_?.trims?.prints?.forEach((trims, index) => { + otherData_.trims?.prints?.forEach((trims, index) => { trims.name = t("Canvas.Elements") + (index + 1); printTrimsLayers.unshift({...trims}); }) - await this.createPrintTrimsLayers(printTrimsLayers, singleLayers); - + if(isUpdate ? updateSpecialGroup : true){ + await this.createPrintTrimsLayers(printTrimsLayers, singleLayers); + } await this.changeCanvas(); } @@ -1432,8 +1442,8 @@ export class CanvasManager { }); tagObject.set('clipPath', transparentMask); } - async createColorLayer(color){ - if(!color) return console.warn("颜色为空不需要添加"); + async createColorLayer(color_){ + const color = color_ || {r:0,g:0,b:0,a:0}; // if(findLayer(this.layers.value, SpecialLayerId.COLOR)) { // return console.warn("画布中已存在颜色图层"); // } @@ -1619,7 +1629,7 @@ export class CanvasManager { // }) // children.push(layer); // } - if(children.length === 0) return; + // if(children.length === 0) return; const groupRect = new fabric.Rect({}); await this.setObjecCliptInfo(groupRect); // 插入组图层 @@ -1638,6 +1648,8 @@ export class CanvasManager { specialType: SpecialType.PRINT_TRIMS_G, }); this.layers.value.splice(groupIndex, 0, groupLayer); + console.log("==========layers", [...this.layers.value]); + } /** diff --git a/src/component/Canvas/CanvasEditor/managers/LayerManager.js b/src/component/Canvas/CanvasEditor/managers/LayerManager.js index 2e105cb8..6ef06696 100644 --- a/src/component/Canvas/CanvasEditor/managers/LayerManager.js +++ b/src/component/Canvas/CanvasEditor/managers/LayerManager.js @@ -199,9 +199,12 @@ export class LayerManager { if (!this.canvas) return; if (isUseOptimize) { // 优化渲染 - 统一批处理 支持异步回调 - await optimizeCanvasRendering(this.canvas, async () => { - // 应用图层交互规则 - await this._applyInteractionRules({ isMoveing }); + await new Promise((resolve) => { + optimizeCanvasRendering(this.canvas, async () => { + // 应用图层交互规则 + await this._applyInteractionRules({ isMoveing }); + resolve(); + }); }); } else { // 直接应用图层交互规则 @@ -333,7 +336,6 @@ export class LayerManager { const objects = this.canvas.getObjects(); const editorMode = this.editorMode || CanvasConfig.defaultTool; const layers = this.layers?.value || []; - // 创建缓存以避免重复查找 const layerMap = {}; layers.forEach((layer) => { diff --git a/src/component/Canvas/canvasExample.vue b/src/component/Canvas/canvasExample.vue index 28416ca2..28a2b94e 100644 --- a/src/component/Canvas/canvasExample.vue +++ b/src/component/Canvas/canvasExample.vue @@ -109,7 +109,32 @@ const exportExtraInfo = async () => { } }; - +// 更新其他图层颜色 +const updateOtherLayersColor = async () => { + const obj = { + color: {rgba: {r:255,g:255,b:0,a:1}}, + } + await canvasEditor?.value?.updateOtherLayers?.(obj); +}; +// 更新其他图层印花 +const updateOtherLayersPrint = async () => { + const obj = { + printObject: { + prints: [ + { + ifSingle: true, + level2Type: "Pattern", + designType: "Library", + path: "/src/assets/images/canvas/yinhua1.jpg", + location: [250, 780], + scale: [0.3, 0.4], + angle: 0, + }, + ] + }, + } + await canvasEditor?.value?.updateOtherLayers?.(obj); +}; const changeCanvas = (command) => { console.log(command); @@ -219,6 +244,20 @@ const customToolsList = ref([ label: "导E", class: "export-btn", }, + { + id: "updateExtraInfo_color", + title: "更新颜色", + action: updateOtherLayersColor, + label: "更C", + class: "export-btn", + }, + { + id: "updateExtraInfo_print", + title: "更新印花", + action: updateOtherLayersPrint, + label: "更P", + class: "export-btn", + }, { id: "exportPNG", title: "导出PNG", //导出画布图片 @@ -309,7 +348,7 @@ const otherData = { level2Type: "Pattern", designType: "Library", path: "/src/assets/images/canvas/yinhua1.jpg", - location: [650, 650], + location: [550, 650], scale: [0.15, 0.2], angle: 0, }, diff --git a/src/component/Canvas/pingpu copy.vue b/src/component/Canvas/pingpu copy.vue new file mode 100644 index 00000000..fafd6f7a --- /dev/null +++ b/src/component/Canvas/pingpu copy.vue @@ -0,0 +1,156 @@ + + + + + \ No newline at end of file diff --git a/src/component/Canvas/pingpu.vue b/src/component/Canvas/pingpu.vue index 525e3017..a1d58dd4 100644 --- a/src/component/Canvas/pingpu.vue +++ b/src/component/Canvas/pingpu.vue @@ -6,38 +6,16 @@ import { fabric } from "fabric-with-all"; import { ref, watch, onMounted } from "vue"; const props = defineProps({ - url: { type: String, required: true }, - offsetX: { type: Number, default: 0 }, // px - offsetY: { type: Number, default: 0 }, // px - angle: { type: Number, default: 0 }, // 角度 - scale: { type: Number, default: 100 }, // % - gapX: { type: Number, default: 0 }, // px - gapY: { type: Number, default: 0 }, // px + list: { type: Array, default: () => [] }, }); - watch( - () => props.url, - () => getOriginalImage() - ); - watch( - () => [ - props.offsetX, - props.offsetY, - props.angle, - props.scale, - props.gapX, - props.gapY, - ], - () => setCanvasData() - ); const el = ref(null); const canvasRef = ref(null); - const canvas = ref(null); const observer = ref(null); - const id = "asfs123121sfe"; + var canvas = null; onMounted(async () => { initCanvas(); - await getOriginalImage(); - setCanvasData(); + await setCanvasData(); + let throttleTimeout = null; let lastRunTime = 0; let trailingTimeout = null; @@ -64,23 +42,21 @@ observer.value.disconnect(); }); const initCanvas = () => { - canvas.value = new fabric.Canvas(canvasRef.value, { + canvas = new fabric.Canvas(canvasRef.value, { selection: false, - evented: false, }); - canvas.value.setWidth(el.value.offsetWidth); - canvas.value.setHeight(el.value.offsetHeight); + canvas.setWidth(el.value.offsetWidth); + canvas.setHeight(el.value.offsetHeight); }; - const updateCanvasSize = () => { - canvas.value.setWidth(el.value.offsetWidth); - canvas.value.setHeight(el.value.offsetHeight); - setCanvasData(); + const updateCanvasSize = async () => { + canvas.setWidth(el.value.offsetWidth); + canvas.setHeight(el.value.offsetHeight); + await setCanvasData(); }; - const originalImage = ref(null); - const getOriginalImage = () => { + const urlToCanvas = (url) => { return new Promise((resolve, reject) => { fabric.Image.fromURL( - props.url, + url, (object) => { const imgElement = object.getElement(); // 创建透明 Canvas @@ -90,62 +66,66 @@ const ctx = tcanvas.getContext("2d"); ctx.clearRect(0, 0, tcanvas.width, tcanvas.height); ctx.drawImage(imgElement, 0, 0); - originalImage.value = tcanvas; resolve(tcanvas); }, { crossOrigin: "anonymous" } ); }); }; - const setCanvasData = () => { - canvas.value.getObjects().forEach((obj) => { - if (obj.id === id) canvas.value.remove(obj); - }); - const image = originalImage.value; - const cwidth = canvas.value.width; - const cheight = canvas.value.height; - const offsetX = props.offsetX; - const offsetY = props.offsetY; - const scaleX = ((cwidth / image.width) * (props.scale / 100)) / 5; - const scaleY = ((cheight / image.height) * (props.scale / 100)) / 5; - const scale = cwidth > cheight ? scaleX : scaleY; - const angle = props.angle; - const gapX = props.gapX; - const gapY = props.gapY; - const patternTransform = fabric.util.composeMatrix({ - scaleX: scale, - scaleY: scale, - angle: angle, - }); - // 创建透明 Canvas - const tcanvas = document.createElement("canvas"); - tcanvas.width = image.width + gapX; - tcanvas.height = image.height + gapY; - const ctx = tcanvas.getContext("2d"); - ctx.clearRect(0, 0, tcanvas.width, tcanvas.height); - ctx.drawImage(image, 0, 0); - const pattern = new fabric.Pattern({ - source: tcanvas, - repeat: "repeat", - patternTransform, - offsetX, // 水平偏移 - offsetY, // 垂直偏移 - }); - const rect = new fabric.Rect({ - id, - width: cwidth, - height: cheight, - top: 0, - left: 0, - // scaleX: 1, - // scaleY: 1, - fill: pattern, - evented: false, - selectable: false, - }); - canvas.value.add(rect); - canvas.value.renderAll(); + const setCanvasData = async () => { + canvas.clear(); + const cwidth = canvas.width; + const cheight = canvas.height; + + for (let i = 0; i < props.list.length; i++) { + let item = props.list[i]; + let image = await urlToCanvas(item.path); + let offsetX = item.location[0]; + let offsetY = item.location[1]; + let scaleX = ((cwidth / image.width) * item.scale[0]) / 5; + let scaleY = ((cheight / image.height) * item.scale[1]) / 5; + let scale = cwidth > cheight ? scaleX : scaleY; + let angle = item.angle; + let gapX = item.object.gapX; + let gapY = item.object.gapY; + let patternTransform = fabric.util.composeMatrix({ + scaleX: scale, + scaleY: scale, + angle: angle, + }); + // 创建透明 Canvas + let tcanvas = document.createElement("canvas"); + tcanvas.width = image.width + gapX; + tcanvas.height = image.height + gapY; + let ctx = tcanvas.getContext("2d"); + ctx.clearRect(0, 0, tcanvas.width, tcanvas.height); + ctx.drawImage(image, 0, 0); + let pattern = new fabric.Pattern({ + source: tcanvas, + repeat: "repeat", + patternTransform, + offsetX, // 水平偏移 + offsetY, // 垂直偏移 + }); + let rect = new fabric.Rect({ + id: item.id, + width: cwidth, + height: cheight, + fill: pattern, + + ...item.object, + }); + canvas.add(rect); + } + canvas.renderAll(); }; + const updataList = (list) => { + + console.log(list); + }; + defineExpose({ + updataList, + }); \ No newline at end of file diff --git a/src/component/Canvas/test.vue b/src/component/Canvas/test.vue index db0be93e..275a8a27 100644 --- a/src/component/Canvas/test.vue +++ b/src/component/Canvas/test.vue @@ -1,121 +1,201 @@ \ No newline at end of file