import { ref } from 'vue' import { fabric } from 'fabric-with-all' import { createId } from '../../tools/tools' import { exportObjectsToImage } from '../tools/exportMethod' export class LayerManager { stateManager: any canvasManager: any layers: any activeID: any constructor(options) { this.stateManager = options.stateManager; this.canvasManager = options.canvasManager; this.layers = ref([]) this.activeID = ref("") } setActiveID(id: string, isActive = true) { this.activeID.value = id if (isActive) { this.canvasManager.setActiveObjectByID(id) } } getLayerByID(id) { return this.layers.value.find((item: any) => item.info.id === id) } setLayerNameByID(id, name: string) { const layer = this.getLayerByID(id) if (layer) { layer.info.name = name this.canvasManager.renderAll() } } setLayerVisibleByID(id, visible: boolean) { const layer = this.getLayerByID(id) if (layer) { layer.set({ visible: visible }) this.canvasManager.renderAll() } } deleteLayerByID(id, isActive = true) { this.canvasManager.deleteObjectById(id) if (id === this.activeID.value && isActive) { this.setActiveID(this.layers.value[0]?.info?.id || "") } } // 拖拽排序 dragSort(id, newIndex) { const index = Math.abs(this.layers.value.length - newIndex - 1) this.canvasManager.dragSort(id, index) } // 更新图层列表 updateLayers() { this.layers.value = this.canvasManager.getObjects().filter((v: any) => !!v?.info?.id).reverse() window["layers"] = this.layers } // 更新图层参数 updateLayerParams(layer, keys = []) { this.layers.value.forEach((item: any) => { if (item.info.id === layer.info.id) { keys.forEach((key: string) => { item.set(key, layer[key]) }) } }) } /** 设置图层位置-不设置默认居中 */ setLayerPosition(layer, options?: any) { const width = this.canvasManager.canvasWidth const height = this.canvasManager.canvasHeight if (options && options.top !== undefined) { layer.set({ top: options.top }) } else { layer.set({ top: height / 2 - layer.height * layer.scaleY / 2 }) } if (options && options.left !== undefined) { layer.set({ left: options.left }) } else { layer.set({ left: width / 2 - layer.width * layer.scaleX / 2 }) } } /** 创建空图层 */ createEmptyLayer() { const emptyLayer = new fabric.Rect({ width: 0, height: 0, fill: 'transparent', info: { id: createId("image"), name: '空图层', } }) this.setLayerPosition(emptyLayer) this.canvasManager.add(emptyLayer) return emptyLayer } /** 创建文本图层 */ createTextLayer(text: string, options?: any) { const textLayer = new fabric.IText(text, { fontSize: 24, fill: '#000', ...(options || {}), info: { id: createId("text"), name: '文本图层', ...(options?.info || {}), } }) this.setLayerPosition(textLayer, options) this.canvasManager.add(textLayer) return textLayer } /** 创建矩形图层 */ createRectLayer(options?: any) { const rectLayer = new fabric.Rect({ width: 100, height: 100, fill: '#000', ...(options || {}), info: { id: createId("rect"), name: '矩形图层', ...(options?.info || {}), } }) this.setLayerPosition(rectLayer, options) this.canvasManager.add(rectLayer) return rectLayer } /** 创建圆形图层 */ createCircleLayer(options?: any) { const circleLayer = new fabric.Circle({ radius: 50, fill: '#000', ...(options || {}), info: { id: createId("circle"), name: '圆形图层', ...(options?.info || {}), } }) this.setLayerPosition(circleLayer, options) this.canvasManager.add(circleLayer) return circleLayer } /** 创建图片图层 */ async createImageLayer(imgOrUrl: string | HTMLImageElement, options?: any) { const canvasWidth = this.canvasManager.canvasWidth const canvasHeight = this.canvasManager.canvasHeight const imageLayer = await new Promise((resolve) => { const url = typeof imgOrUrl === 'string' ? imgOrUrl : imgOrUrl.src fabric.Image.fromURL(url, (img) => { const width = img.width const height = img.height const scaleX = width > canvasWidth ? canvasWidth * 0.8 / width : 1 const scaleY = height > canvasHeight ? canvasHeight * 0.8 / height : 1 const scale = Math.min(scaleX, scaleY) img.set({ scaleX: scale, scaleY: scale, ...(options || {}), info: { id: createId("image"), name: "图片图层", ...(options?.info || {}), } }) resolve(img) }) }) as fabric.Object this.setLayerPosition(imageLayer, options) this.canvasManager.add(imageLayer) this.setActiveID(imageLayer.info.id) return imageLayer } /** 合并图层 */ async imageMergeToLayer(targetLayer: fabric.Object, fabricImage: fabric.Object) { const info = await exportObjectsToImage([targetLayer, fabricImage], true) const mergedImage = await new Promise((resolve) => { fabric.Image.fromURL(info.url, (img) => { img.set({ left: info.left, top: info.top, info: { id: createId("image"), name: targetLayer?.info?.name || "合并图层", } }) resolve(img) }) }) // console.log(mergedImage) const index = this.canvasManager.getObjects().indexOf(targetLayer); this.deleteLayerByID(targetLayer.info.id, false) this.setActiveID(mergedImage.info.id, false) this.canvasManager.add(mergedImage, false); this.canvasManager.canvas.moveTo(mergedImage, index); this.canvasManager.renderAll() this.updateLayers() return true; } /** 设置激活对象可擦除 */ setActiveObjectErasable() { const objects = this.canvasManager.getObjects() objects.forEach((item: any) => { item.set({ erasable: item.info.id === this.activeID.value }) }) } dispose() {} }