深度画布功能
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
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
|
||||
@@ -11,7 +14,12 @@ export class LayerManager {
|
||||
this.layers = ref([])
|
||||
this.activeID = ref("")
|
||||
}
|
||||
setActiveID(id: string) { this.activeID.value = id }
|
||||
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)
|
||||
}
|
||||
@@ -31,8 +39,11 @@ export class LayerManager {
|
||||
this.canvasManager.renderAll()
|
||||
}
|
||||
}
|
||||
deleteLayerByID(id) {
|
||||
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) {
|
||||
@@ -41,6 +52,156 @@ export class LayerManager {
|
||||
}
|
||||
// 更新图层列表
|
||||
updateLayers() {
|
||||
this.layers.value = this.canvasManager.getObjects().reverse()
|
||||
this.layers.value = this.canvasManager.getObjects().filter((v: any) => !!v?.info?.id).reverse()
|
||||
}
|
||||
}
|
||||
|
||||
/** 设置图层位置-不设置默认居中 */
|
||||
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
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user