当前位置: 代码迷 >> 综合 >> fabric 画板,绘制几何图形复杂图形
  详细解决方案

fabric 画板,绘制几何图形复杂图形

热度:65   发布时间:2024-01-11 20:45:27.0

一、安装

npm install fabric

二、引入创建

import { fabric } from 'fabric'initCanvas () {// 初始化一张画布this.fabricObj = new fabric.Canvas('canvas', {isDrawingMode: true,selectable: false,selection: false,devicePixelRatio: true // Retina 高清屏 屏幕支持})// 设置笔刷的颜色和宽度this.fabricObj.freeDrawingBrush.color = this.drawOption.colorthis.fabricObj.freeDrawingBrush.width = this.drawOption.lineWidth// 设置画笔的大小,整屏可书写this.fabricObj.setWidth(document.body.clientWidth)this.fabricObj.setHeight(document.body.clientHeight)// 如果传过来的数据中自带有画笔的笔记if (this.currentPage.fabricHistoryJson) {const state = JSON.parse(this.currentPage.fabricHistoryJson)this.fabricHistoryJson = statethis.fabricObj.loadFromJSON(state[state.length - 1])} else {this.fabricObj.clear()}// 绑定画板事件this.fabricObjAddEvent()},

三、绑定画板的一些事件

       主要是画笔的一些事件,以及选中删除事件

fabricObjAddEvent () {this.fabricObj.on({'mouse:down': (o) => {this.toggleClear()this.mouseFrom.x = o.pointer.xthis.mouseFrom.y = o.pointer.ythis.doDrawing = trueif (this.currentTool === 'text') {this.drawText()}},'mouse:up': (o) => {this.mouseTo.x = o.pointer.xthis.mouseTo.y = o.pointer.ythis.drawingObject = nullthis.moveCount = 1this.doDrawing = falsethis.updateModifications(true)},'mouse:move': (o) => {if (this.moveCount % 2 && !this.doDrawing) {// 减少绘制频率return}this.moveCount++this.mouseTo.x = o.pointer.xthis.mouseTo.y = o.pointer.ythis.drawing()},// 对象移动时间'object:moving': (e) => {e.target.opacity = 0.5},// 增加对象'object:added': (e) => {},'object:modified': (e) => {e.target.opacity = 1// const object = e.targetthis.updateModifications(true)},'selection:created': (e) => {if (e.selected.length > 1 && e.target._objects) {// 多选删除var etCount = e.target._objects.lengthfor (var etindex = 0; etindex < etCount; etindex++) {this.fabricObj.remove(e.target._objects[etindex])}} else {// 单选删除this.fabricObj.remove(e.target)}this.fabricObj.discardActiveObject() // 清楚选中框this.updateModifications(true)}})},// 储存历史记录updateModifications (savehistory) {if (savehistory === true) {this.fabricHistoryJson.push(JSON.stringify(this.fabricObj))}}

四、绘制各种图形

       路径的绘制方法以五边形作为例子

fabricObject = new fabric.Path(drawPentagon(this.mouseFrom.x, this.mouseFrom.y, this.mouseTo.x, this.mouseTo.y), {right: this.mouseFrom.x,bottom: this.mouseFrom.y,stroke: this.drawOption.color,strokeWidth: this.drawOption.lineWidth,strokeLineJoin: 'round',fill: 'rgba(255, 255, 255, 0)'
})if (fabricObject) {this.fabricObj.add(fabricObject)
}drawPentagon = (fromX, fromY, toX, toY) => {const width = toX - fromXconst height = toY - fromYlet path = 'M' + fromX + ' ' + fromYpath += 'L' + (fromX + width / 2) + ' ' + (fromY - (height * 0.618))path += 'L' + (fromX + width) + ' ' + fromYpath += 'L' + (toX - width * 0.191) + ' ' + toYpath += 'L' + (fromX + width * 0.191) + ' ' + toYpath += 'z'return path
}

复杂的图形需要使用  fabric.Group

fabricObject = new fabric.Group(drawSmile(this.mouseFrom.x, this.mouseFrom.y, this.mouseTo.x, this.mouseTo.y, {right: this.mouseFrom.x,bottom: this.mouseFrom.y,stroke: this.drawOption.color,strokeWidth: this.drawOption.lineWidth,srokeLineJoin: 'round',fill: 'rgba(255, 255, 255, 0)'
}))
if (fabricObject) {this.fabricObj.add(fabricObject)
}drawSmile = (fromX, fromY, toX, toY, pathConfig) => {const R = Math.sqrt(Math.pow((toX - fromX), 2) + Math.pow((toY - fromY), 2)) / 2const px = (toX - fromX) > 0 ? 0 : (toX - fromX)const py = (toY - fromY) > 0 ? 0 : (toY - fromY)const circle = new fabric.Circle({left: fromX + px,top: fromY + py,radius: R,stroke: pathConfig.stroke,strokeWidth: pathConfig.strokeWidth,fill: pathConfig.fill})const leftEye = new fabric.Circle({left: fromX + px + (R / 2),top: fromY + py + R / 2,radius: R / 10,stroke: pathConfig.stroke,strokeWidth: pathConfig.strokeWidth,fill: pathConfig.stroke})const rightEye = new fabric.Circle({left: fromX + px + ((R) / 3) + (R),top: fromY + py + (R) / 2,radius: R / 10,stroke: pathConfig.stroke,strokeWidth: pathConfig.strokeWidth,fill: pathConfig.stroke})const mouth = new fabric.Circle({left: fromX + px + (R) / 2,top: fromY + py + 2 * (R) / 3,radius: R / 2,angle: 0,startAngle: 0,endAngle: Math.PI,stroke: pathConfig.stroke,strokeWidth: pathConfig.strokeWidth,fill: pathConfig.stroke})return [circle, leftEye, rightEye, mouth]
}

  正方体

drawCube = (fromX, fromY, toX, toY, pathConfig) => {const width = toX - fromXconst height = toY - fromYlet path1 = 'M' + (fromX + width / 4) + ' ' + fromYpath1 += 'L' + toX + ' ' + fromYpath1 += 'L' + (toX - width / 4) + ' ' + (fromY + height / 4)path1 += 'L' + fromX + ' ' + (fromY + height / 4)path1 += 'z'let path2 = 'M' + fromX + ' ' + (fromY + height / 4)path2 += 'L' + fromX + ' ' + toYpath2 += 'L' + (toX - width / 4) + ' ' + toYpath2 += 'L' + toX + ' ' + (toY - height / 4)path2 += 'L' + toX + ' ' + fromYconst path3 = 'M' + (toX - width / 4) + ' ' + (fromY + height / 4) + 'L' + (toX - width / 4) + ' ' + toYreturn [new fabric.Path(path1, pathConfig), new fabric.Path(path2, pathConfig), new fabric.Path(path3, pathConfig)]
}

圆柱体

drawCylinder = (fromX, fromY, toX, toY, pathConfig) => {const Tuoyuan = new fabric.Ellipse({left: fromX,top: fromY,originX: 'center',originY: 'center',rx: Math.abs(fromX - toX) / 2,ry: 30,stroke: pathConfig.stroke,strokeWidth: pathConfig.strokeWidth,fill: 'rgba(255,255,255,0)'})const directionX = toX - fromXconst directionY = toY - fromYlet sweepFlagif ((directionX > 0 && directionY > 0) || (directionX < 0 && directionY < 0)) {sweepFlag = '0'} else {sweepFlag = '1'}const huPath = 'M' + (fromX - (toX - fromX) / 2) + ',' + toY + ' A' + Math.abs(fromX - toX) / 2 + ',30,0,0,' + sweepFlag + ',' + (fromX + (toX - fromX) / 2) + ',' + toYconst hu = new fabric.Path(huPath, pathConfig)const pathleft = 'M' + (fromX - (toX - fromX) / 2) + ' ' + fromY + 'L' + (fromX - (toX - fromX) / 2) + ' ' + toYconst lineleft = new fabric.Path(pathleft, pathConfig)const pathright = 'M' + (fromX + (toX - fromX) / 2) + ' ' + fromY + 'L' + (fromX + (toX - fromX) / 2) + ' ' + toYconst lineright = new fabric.Path(pathright, pathConfig)return [Tuoyuan, hu, lineleft, lineright]
}