import { OperationType, OperationTypes } from "../tools/layerHelper"; import { getStarArr, getArrowPath, distance, angleBetweenPointsDegrees } from "../tools/canvasMethod"; import { fabric } from 'fabric-with-all' /** 形状管理器 */ export class ShapeToolManager { // 管理器 canvasManager: any stateManager: any layerManager: any toolManager: any isDragging: boolean = false startX: number = 0 startY: number = 0 demoObject: any tools = [ OperationType.RECTANGLE, OperationType.LINE, OperationType.ARROW, OperationType.ELLIPSE, OperationType.TRIANGLE, OperationType.STAR, ] constructor(options) { this.canvasManager = options.canvasManager this.stateManager = options.stateManager this.layerManager = options.layerManager this.toolManager = options.toolManager } mouseDownEvent(e) { this.isDragging = false this.demoObject = null this.startX = e.absolutePointer.x this.startY = e.absolutePointer.y const currentTool = this.toolManager.currentTool.value if (currentTool === OperationType.RECTANGLE) { this.demoObject = this.downRectangle() } else if (currentTool === OperationType.LINE) { this.demoObject = this.downLine() } else if (currentTool === OperationType.ELLIPSE) { this.demoObject = this.downEllipse() } else if (currentTool === OperationType.TRIANGLE) { this.demoObject = this.downTriangle() } else if (currentTool === OperationType.STAR) { this.demoObject = this.downStar() } else if (currentTool === OperationType.ARROW) { this.demoObject = this.downArrow() } if (!this.demoObject) return; this.demoObject.set({ evented: false, }) this.demoObject.set this.isDragging = true this.canvasManager.canvas.add(this.demoObject) this.canvasManager.canvas.renderAll() } mouseMoveEvent(e) { if (!this.isDragging) return; var width = e.absolutePointer.x - this.startX var height = e.absolutePointer.y - this.startY var left = this.startX var top = this.startY if (width < 0) { left += width width = -width } if (height < 0) { top += height height = -height } const currentTool = this.toolManager.currentTool.value if (currentTool === OperationType.RECTANGLE) { this.moveRectangle({ width, height, left, top }) } else if (currentTool === OperationType.LINE) { this.moveLine(e.absolutePointer) } else if (currentTool === OperationType.ELLIPSE) { this.moveEllipse({ width, height, left, top }) } else if (currentTool === OperationType.TRIANGLE) { this.moveTriangle({ width, height, left, top }) } else if (currentTool === OperationType.STAR) { this.moveStar({ width, height, left, top }) } else if (currentTool === OperationType.ARROW) { this.moveArrow(e.absolutePointer) } this.demoObject.set({ evented: false, }) this.canvasManager.canvas.renderAll() } mouseUpEvent(e) { if (!this.isDragging) return; this.isDragging = false; const object = this.demoObject.toJSON("evented") const currentTool = this.toolManager.currentTool.value if (currentTool === OperationType.RECTANGLE) { this.upRectangle(object) } else if (currentTool === OperationType.LINE) { this.upLine(object) } else if (currentTool === OperationType.ELLIPSE) { this.upEllipse(object) } else if (currentTool === OperationType.TRIANGLE) { this.upTriangle(object) } else if (currentTool === OperationType.STAR) { this.upStar(object) } else if (currentTool === OperationType.ARROW) { this.upArrow(object) } this.canvasManager.canvas.remove(this.demoObject) this.demoObject = null this.canvasManager.canvas.renderAll() } /** 绘制矩形 */ downRectangle() { const rect = new fabric.Rect({ left: this.startX, top: this.startY, width: 0, height: 0, fill: '#000', }) return rect } moveRectangle({ width, height, left, top }) { this.demoObject.set({ width, height, left, top }) } upRectangle(object) { if (object.width === 0) object.width = 100 if (object.height === 0) object.height = 100 this.layerManager.createRectLayer(object, true) } /** 绘制直线 */ downLine() { const line = new fabric.Line([this.startX, this.startY, this.startX, this.startY], { stroke: 'black', // 线条颜色 strokeWidth: 2 // 线条粗细 }) return line } moveLine({ x, y }) { this.demoObject.set({ x1: this.startX, y1: this.startY, x2: x, y2: y, }) } upLine(object) { this.layerManager.createLineLayer(object, true) } /** 绘制椭圆 */ downEllipse() { const circle = new fabric.Ellipse({ left: this.startX, top: this.startY, fill: '#000', }) return circle } moveEllipse({ width, height, left, top }) { this.demoObject.set({ rx: width / 2, ry: height / 2, left, top }) } upEllipse(object) { if (object.rx === 0) object.rx = 50 if (object.ry === 0) object.ry = 50 this.layerManager.createEllipseLayer(object, true) } /** 绘制三角形 */ downTriangle() { const triangle = new fabric.Triangle({ left: this.startX, top: this.startY, width: 0, height: 0, fill: '#000', }) return triangle } moveTriangle({ width, height, left, top }) { this.demoObject.set({ width, height, left, top }) } upTriangle(object) { if (object.width === 0) object.width = 100 if (object.height === 0) object.height = 100 this.layerManager.createTriangleLayer(object, true) } /** 绘制五角星 */ downStar() { const star = new fabric.Polygon(getStarArr(0, 0), { left: this.startX, top: this.startY, width: 0, height: 0, fill: '#000', strokeLineJoin: 'round', // 圆角连接 strokeLineCap: 'round', // 圆角端点 }); return star } moveStar({ width, height, left, top }) { this.demoObject.set({ left, top, width, height, points: getStarArr(width, height) }) } upStar(object) { if (object.width === 0) object.width = 100 if (object.height === 0) object.height = 100 this.layerManager.createStarLayer(object, true) } /** 绘制箭头 */ downArrow() { return new fabric.Path(); } moveArrow({ x, y }) { const width = distance(this.startX, this.startY, x, y) const angle = angleBetweenPointsDegrees(this.startX, this.startY, x, y) this.canvasManager.canvas.remove(this.demoObject) const arrow = new fabric.Path(getArrowPath(width, 10), { left: this.startX, top: this.startY, stroke: '#000', // 只设置边框颜色 strokeWidth: 3, // 边框宽度 fill: 'transparent', // 不填充 strokeLineCap: 'round', strokeLineJoin: 'round', originY: 'center', angle: angle, }); this.canvasManager.canvas.add(arrow) this.demoObject = arrow } upArrow(object) { if (object.originY !== "center") { this.layerManager.createArrowLayer({ left: this.startX, top: this.startY, }, true) } else { this.layerManager.createArrowLayer(object, true) } } dispose() { } }