网站开发所需技能,网站采用什么字体,江苏省句容建设局网站,怀化公积金网站目录 前言
一、Fabric.js简介
二、开始
1、引入Fabric.js
2、在main.js中使用
3、初始化画布
三、方法
四、事件
1、常用事件
2、事件绑定
3、事件解绑
五、canvas常用属性
六、对象属性
1、基本属性
2、扩展属性
七、图层层级操作
八、复制和粘贴
1、复制
2…目录 前言
一、Fabric.js简介
二、开始
1、引入Fabric.js
2、在main.js中使用
3、初始化画布
三、方法
四、事件
1、常用事件
2、事件绑定
3、事件解绑
五、canvas常用属性
六、对象属性
1、基本属性
2、扩展属性
七、图层层级操作
八、复制和粘贴
1、复制
2、粘贴
九、锁定
1、静止水平移动lockMovementX
2、静止垂直移动lockMovementY
3、静止旋转lockRotation
4、静止水平缩放lockScalingX
5、静止垂直缩放lockScalingY
6、限制拖动区域
十、分组
十一、动画
十二、图像滤镜
十三、渐变
1、线性渐变
2、径向渐变
十四、拖拽和缩放画布
1、拖拽画布
2、以画布中心点为基准手动缩放
3、以鼠标指针位置为基准缩放
十五、右键菜单删除
十六、自由绘画
1、开启绘图模式
2、关闭绘图模式
十七、绘制背景图片
1、方式一通过img元素添加
2、方式二通过图片路径添加
十八、绘制文本
1、基础用法
2、文本修饰
3、可编辑文本
十九、绘制线和路径
1、绘制直线
2、绘制虚线
3、绘制路径
二十、自由绘制矩形
二十一、自由绘制圆形
二十二、自由绘制椭圆形
二十三、自由绘制三角形
二十四、自由绘制多边形 前言 演示Demo前端可视化demo Demo源码https://gitee.com/k21vin/front-end-data-visualization 本文章所有的gif图片由于录屏软件问题上面的鼠标位置都是错位显示的
一、Fabric.js简介 Fabric.js是一个对canvas进行封装的Javascript库在原生canvas之上提供了交互式对象模型通过简洁的api就可以在画布上进行丰富的操作。 它主要的功能包括在canvas上创建和填充图形比如矩形、圆形、多边形生成的图像自带缩放、旋转、拖拽等功能还可以给图形填充渐变颜色各个图形可以相互组合等等。
二、开始
1、引入Fabric.js
npm i fabric --save
2、在main.js中使用
// main.js
import fabric from fabric
Vue.use(fabric)
3、初始化画布
templatecanvas idcanvas/canvas
/templatescript
export default {data () {canvas: null, // 画布对象},mounted() {this.canvas new fabric.Canvas(canvas, {width: 300,height: 200})}
/script
三、方法
canvas.add(object) // 添加对象
canvas.remove(object) // 删除对象
canvas.setWidth(width) // 设置canvas宽度
canvas.setHeight(height) // 设置canvas高度
canvas.setDimensions({width, height})// 一键设置宽高
canvas.getObjects() // 获取所有对象
canvas.getActiveObject() // 获取选中的对象
canvas.clear() // 清除画布中所有对象
canvas.renderAll() // 重绘
canvas.requestRenderAll() // 请求重新渲染
canvas.getZoom() // 获取画布当前缩放值
canvas.sendToBack(object) // 移到对象到最底层
canvas.viewportCenterObjectH(object) // 水平居中对象
canvas.viewportCenterObjectV(object) // 垂直居中对象
canvas.viewportCenterObject(object) // 垂直水平居中对象
canvas.fxCenterObjectH(object) // 动画水平居中对象
canvas.fxCenterObjectV(object) // 动画垂直居中对象
canvas.fxCenterObject(object) // 动画垂直水平居中对象let canvasJsonData JSON.stringify(canvas.toJSON()) // 将画布序列化成json数据
let canvasSvgData canvas.toSVG() // 将画布序列化成svg数据
canvas.loadFromJSON(canvasJsonData) // 反序列化Json数据
四、事件
1、常用事件
mouse: down // 鼠标按下事件
mouse: move // 鼠标移动事件
mouse: up // 鼠标移动事件
mouse: over // 鼠标移入事件
mouse: out // 鼠标移出事件
mouse: dblclick // 鼠标双击事件
object: added // 对象被添加事件
object: removed // 对象被删除事件
object: modified // 对象被修改事件
object: rotating // 对象被旋转事件
object: scaling // 对象被缩放事件
object: moving // 对象被移动事件
2、事件绑定
canvas.on(mouse: wheel, (opt) {console.log(opt)
})
3、事件解绑
canvas.off(mouse: wheel)
五、canvas常用属性
canvas.selection true // 画布是否可选中 默认为true、false不可选中
canvas.selectionColor transparent // 画布鼠标框选时的背景色
canvas.selectionBorderColor transparent// 画布鼠标框选时的边框颜色
canvas.selectionLineWidth 6 // 画布鼠标框选时的边框厚度
canvas.selectionDashArray [30, 4, 10] // 画布鼠标框选时边框虚线规则
canvas.selectionFullyContained true // 只选择完全包含在拖动选择矩形中的形状
canvas.backgroundColor #2E3136 // 画布背景色
canvas.hoverCursor pointer // 鼠标光标样式 default、pointer、move等
canvas.skipTargetFind true // 整个画板元素不能被选中
canvas.fireRightClick true // 启用右键options.button的数字为3
canvas.stopContextMenu true // 禁止默认右键菜单 Fabric.js 可以通过 viewportTransform 属性配置画布的视窗属性
canvas.viewportTransform[4] 100
canvas.viewportTransform[5] 100 viewportTransform 是一个数组里面有6个元素默认值是 [1, 0, 0, 1, 0, 0]。从下标0开始它们分别代表
[0]: 水平缩放x轴方向
[1]: 水平倾斜x轴方向
[2]: 垂直倾斜y轴方向
[3]: 垂直缩放y轴方向
[4]: 水平移动x轴方向
[5]: 垂直移动y轴方向
六、对象属性
1、基本属性
let circle new fabric.Circle({top: 100, // y坐标left: 100, // x坐标fill: #17b978, // 填充色radius: 50 // 半径
})
rect.top 100 // y坐标
rect.left 100 // x坐标
rect.width 100 // 矩形宽度
rect.height 100 // 矩形高度
circle.radius 50 // 圆半径
rect.fill #17b978 // 填充色
rect.stroke #FE5332 // 线条颜色
rect.strokeWidth 10 // 线条宽度
rect.strokeMiterLimit index // 可以用来记录当前选中的rectList列表的索引
2、扩展属性
circle.set({hasBorders: false
}
circle.selectable false // 控件不能被选择不会被操作
circle.hasControls false // 只能移动不能编辑操作
circle.hasBorders false // 选中时是否显示边true显示默认
circle.borderColor red // 选中时边的颜色
circle.borderScaleFactor 5 // 选中时边的粗细
circle.borderDashArray [20, 5, 10, 7] // 选中时虚线边的规则
circle.transparentCorners false // 选中时角是否是空心 true空心 false实心
circle.cornerColor #a1de93, // 选中时角的颜色
circle.cornerStrokeColor pink // 选中时角的边框的颜色
circle.cornerStyle circle // 选中时角的属性 rect矩形默认、circle圆形
circle.cornerSize 20 // 选中时角的大小为20
circle.cornerDashArray [10, 2, 6] // 选中时虚线角的规则
circle.selectionBackgroundColor #ffc300 // 选中时选框的背景色
circle.padding 20 // 选中时选框离图形的距离
circle.borderOpacityWhenMoving 0.6 // 当对象活动和移动时对象控制边界的不透明度
triangle.perPixelTargetFind true // 选择三角形空白位置的时候无法选中false可以选中默认
七、图层层级操作
canvas.bringToFront(rect) // 移到顶层
canvas.sendToBack(rect) // 移到底层
canvas.bringForward(rect) // 上移一层
canvas.sendBackwards(rect) // 下移一层
canvas.moveTo(0) // 移动到指定层
八、复制和粘贴 1、复制
handleCopy() {if (!canvas.getActiveObject()) {this.$message.warning(请先选择元素)return}this.canvas.getActiveObject().clone(cloned {this.cloneObjects cloned})
}
2、粘贴
handlePaste() {if (!this.cloneObjects) {return this.$message.warning(还没复制过任何内容)}this.cloneObjects.clone(cloned {this.canvas.discardActiveObject() // 取消选择// 设置新内容的坐标位置cloned.set({left: cloned.left 10,top: cloned.top 10,evented: true})if (cloned.type activeSelection) { // 如果复制的是多个对象则需要遍历克隆对象cloned.canvas this.canvas;cloned.forEachObject(obj {this.canvas.add(obj)})cloned.setCoords()} else {this.canvas.add(cloned)}this.cloneObjects.top 10this.cloneObjects.left 10this.canvas.setActiveObject(cloned)this.canvas.requestRenderAll()})
}
九、锁定 Fabric对象可以添加一些属性进行锁定例如静止水平移动、静止垂直移动静止缩放等等
1、静止水平移动lockMovementX let rect new fabric.Rect({width: 100,height: 50,fill: #ffde7d,top: 20,left: 20
})
rect.lockMovementX true
canvas.add(rect)
2、静止垂直移动lockMovementY let rect new fabric.Rect({width: 100,height: 50,fill: #ffde7d,top: 20,left: 20
})
rect.lockMovementY true
3、静止旋转lockRotation let rect new fabric.Rect({width: 100,height: 50,fill: #ff9a3c,top: 60,left: 160
})
rect.lockRotation true
4、静止水平缩放lockScalingX let rect new fabric.Rect({width: 100,height: 50,fill: #ffde7d,top: 20,left: 20
})
rect.lockScalingX true
5、静止垂直缩放lockScalingY let rect new fabric.Rect({width: 100,height: 50,fill: #f95959,top: 20,left: 20
})
rect.lockScalingY true
6、限制拖动区域 let boundingBox new fabric.Rect({top: 100,left: 100,width: 600,height: 400,fill: #f95959,selectable: false
})
let movingBox new fabric.Rect({top: 150,left: 150,width: 100,height: 100,fill: yellow,hasBorders: false,hasControls: false,hoverCursor: move
})
this.canvas.add(boundingBox);
this.canvas.add(movingBox);
this.canvas.on(object:moving, (opt) {let top movingBox.top;let left movingBox.left;let topBound boundingBox.top;let bottomBound topBound boundingBox.height;let leftBound boundingBox.left;let rightBound leftBound boundingBox.width;opt.target.left Math.min(Math.max(left, leftBound), rightBound - movingBox.width)opt.target.top Math.min(Math.max(top, topBound), bottomBound - movingBox.height)
})
十、分组 Groups是Fabric最强大的功能之一它可以将任意数量的Fabric对象组合在一起形成一个小组分组后所有对象都可以一起移动、修改、缩放、旋转甚至更改其外观等 let group new fabric.Group([circle, text], {left: 100,top: 100,angle: -10
})
canvas.add(group) 修改分组的某个对象的属性 group.item(0).set(fill,red);
group.item(1).set({text:trololo,fill:white
}) 分组时要记住的另一件事是对象的状态。例如在与图像组成组时需要确保这些图像已完全加载 fabric.Image.fromURL(logo, img {let img1 img.scale(0.3).set({left: 0, top: 0})fabric.Image.fromURL(logo, img {let img2 img.scale(0.3).set({left: 80, top: 0})fabric.Image.fromURL(logo, img {let img3 img.scale(0.3).set({left: 160, top: 0})let group new fabric.Group([img1, img2, img3], {left: 10,top: 400})canvas.add(group)})})
})
十一、动画 每个Fabric对象都有一个animate方法该方法可以动画化该对象animate(动画属性动画的结束值[动画的详细信息]) let rect new fabric.Rect({left: 100,top: 100,width: 100,height: 100,fill: red
})
rect.animate(angle, 45, {onChange: canvas.renderAll.bind(canvas)
})
canvas.add(rect) 第一个参数是要设置动画的属性。第二个参数是动画的结束值。如果矩形具有-15°的角度并且我们传递了45则动画将从-15°变为45°。第三个参数是一个可选对象用于指定动画的详细信息-持续时间回调缓动等 rect.animate(angle, 45, {from: 0, // 允许指定可设置动画的属性的起始值如果我们不希望使用当前值duration: 1000, // 默认为500ms可用于更改动画的持续时间easing: fabric.util.ease.easeOutBounce, // 缓动功能 easeOutBounce、easeInCubic、easeOutCubic、easeInElastic、easeOutElastic、easeInBounce、easeOutExpoonChange: canvas.renderAll.bind(canvas), // 在每次刷新时都会执行onComplete: (e) { console.log(e) } // 在动画结束时调用的回调
}) animate的一个方便之处在于它还支持相对值 // 向右移动100px
rect.animate(left, 100, {onChange: canvas.renderAll.bind(canvas)
})// 逆时针旋转5度
rect.animate(angle, -5, {onChange: canvas.renderAll.bind(canvas)
})
十二、图像滤镜 fabric.Image的每个实例都具有“ filters”属性该属性是一个简单的过滤器数组。该阵列中的每个过滤器都是Fabric过滤器之一的实例。或您自己的自定义过滤器的实例。 let url http://localhost:82/public/img/5.png // 图片url
let base64Url await this.imgUrlToBase64(url) // 图片base64 url
// 正常照片
fabric.Image.fromURL(url, img {img.scale(0.3)canvas.add(img)
})// 单个滤镜
fabric.Image.fromURL(base64Url, img {img.scale(0.3)img.left 300// 添加滤镜img.filters.push(new fabric.Image.filters.Grayscale())// 图片加载完成之后应用滤镜效果img.applyFilters()canvas.add(img)
})// 叠加滤镜
fabric.Image.fromURL(base64Url, img {img.scale(0.3)img.set({left: 300,top: 250,})img.filters.push(new fabric.Image.filters.Grayscale(),new fabric.Image.filters.Sepia(), //色偏new fabric.Image.filters.Brightness({ brightness: 0.2 }) //亮度)img.applyFilters()canvas.add(img)
}) 说明这里图片可能会出错放本地图片地址会报“Cannot read property naturalWidth of null”的错误直接放网络图片地址会报“Failed to execute texImage2D on WebGLRenderingContext: The image element contains cross-origin data, and may not be loaded.”的错误。解决方法就是将转为Base64格式
十三、渐变 Fabric支持在所有对象上设置填充或描边属性的渐变首先创建渐变然后将其分配给填充或描边。
1、线性渐变 // 圆
let circle new fabric.Circle({left: 100,top: 100,radius: 50,
})
let gradient new fabric.Gradient({type: linear, // linear or radialgradientUnits: pixels, // pixels or pencentage 像素 或者 百分比coords: { x1: 0, y1: 0, x2: circle1.width, y2: 0 }, // 至少2个坐标对x1y1和x2y2将定义渐变在对象上的扩展方式colorStops:[ // 定义渐变颜色的数组{ offset: 0, color: red },{ offset: 0.2, color: orange },{ offset: 0.4, color: yellow },{ offset: 0.6, color: green },{ offset: 0.8, color: blue },{ offset: 1, color: purple },]
})
circle.set(fill, gradient);
canvas.add(circle)
2、径向渐变 let circle new fabric.Circle({left: 100,top: 100,radius: 50
})
let gradient new fabric.Gradient({type: radial,coords: {r1: 50,r2: 0,x1: 50,y1: 50,x2: 50,y2: 50,},colorStops: [{ offset: 0, color: #fee140 },{ offset: 1, color: #fa709a }]
})
circle.set(fill, gradient);
canvas.add(circle)
十四、拖拽和缩放画布
1、拖拽画布 scriptexport default {data() {return {lastPosX: 0, // 上次鼠标位置X坐标lastPosY: 0, // 上次鼠标位置Y坐标isDragging: false, // 是否可以拖拽画布}},mounted() {... // 初始化canvasthis.canvas.on(mouse:down, this.onMouseDown)this.canvas.on(mouse:move, this.onMouseMove)this.canvas.on(mouse:up, this.onMouseUp)},methods: {// 监听鼠标按下事件onMouseDown(opt) {this.lastPosX opt.e.clientXthis.lastPosY opt.e.clientYthis.isDragging true},// 监听鼠标移动事件onMouseMove(opt) {if (this.isDragging) {this.canvas.viewportTransform[4] opt.e.clientX - this.lastPosXthis.canvas.viewportTransform[5] opt.e.clientY - this.lastPosYthis.canvas.requestRenderAll()this.lastPosX opt.e.clientXthis.lastPosY opt.e.clientY}},// 监听鼠标松开事件onMouseUp(opt) {if (this.isDragging) {this.canvas.setViewportTransform(this.canvas.viewportTransform)this.isDragging false}}}}
/script
2、以画布中心点为基准手动缩放 templateel-tooltip content放大 placementbottom-startspan classiconfont icon-fangda clickonManualScale(-100)/span/el-tooltipel-tooltip content缩小 placementbottom-startspan classiconfont icon-suoxiao clickonManualScale(100)/span/el-tooltip
/template
script
export default {// 中心点缩放画布onManualScale(delta) {let zoom canvas.getZoom() // 获取画布当前缩放值zoom * 0.999 ** deltazoom zoom 10 ? 10 : (zoom 0.1 ? 0.1 : zoom) // 最大放大10倍最小缩小至10%canvas.zoomToPoint({ // 以画布中心点为基准缩放x: this.canvasBoxWidth / 2, // canvasBoxWidth 画布宽度y: this.canvasBoxHeight / 2 // canvasBoxHeight 画布高度}, zoom)}
}
/script
3、以鼠标指针位置为基准缩放 this.canvas.on(mouse:wheel, this.onMouseWheel)// 监听鼠标放大缩小事件
onMouseWheel(opt) {let delta opt.e.deltaY // 滚轮向上滚一下是 -100向下滚一下是 100let zoom this.canvas.getZoom() // 获取画布当前缩放值zoom * 0.999 ** deltazoom zoom 10 ? 10 : (zoom 0.1 ? 0.1 : zoom) // 最大放大10倍最小缩小至10%this.canvas.zoomToPoint({ // 以鼠标指针位置为基准缩放x: opt.e.offsetX,y: opt.e.offsetY}, zoom)opt.e.preventDefault()opt.e.stopPropagation()
}
十五、右键菜单删除 templatediv classcanvas-box refcanvasBoxcanvas idcanvas/canvasdiv iddelMenu refdelMenu v-showisShowDelMenu :styledelMenuStyle contextmenu.preventel-button typeiconButton iconh-icon-delete clickhandleDeleteMenu删除/el-button/div/div
/template
script
export default {name: PointerDetail,data () {return {canvas: null,activeEle: null, // 上次选中元素isShowDelMenu: false, // 是否显示删除弹窗delMenuStyle: // 删除弹窗定位样式}},mounted() {this.init()},methods: {// 初始化init() {this.canvas new fabric.Canvas(canvas, {fireRightClick: true, // 启用右键button的数字为3stopContextMenu: true, // 禁止默认右键菜单})this.canvas.on(mouse:down, this.onMouseDown)},// 监听鼠标按下事件onMouseDown(opt) {// 还原上次选中状态if (this.activeEle) {this.activeEle.set(fill, transparent)this.canvas.renderAll()}this.activeEle opt.target || null// 按下鼠标右键if (opt.button 3) {// 点击到非图片控件 显示删除弹窗和填充控件背景色if (opt.target opt.target.type ! image) {this.activeEle.set(fill, rgba(100, 100, 255, 0.3))this.canvas.renderAll()this.isShowDelMenu truethis.$nextTick(() {this.delMenuStyle this.getMenuStyle(this.$refs.delMenu, opt)})} else {// 否则隐藏删除弹窗this.hiddenMenu()}// 按下鼠标左键} else {this.hiddenMenu()}},// 获取弹窗坐标getMenuStyle(ele, opt) {let menuWidth ele.offsetWidthlet menuHeight ele.offsetHeightlet pointX opt.pointer.x 2let pointY opt.pointer.y 2if (this.$refs.canvasBox.offsetWidth - pointX menuWidth) {pointX - menuWidth}if (this.$refs.canvasBox.offsetHeight - pointY menuHeight) {pointY - menuHeight}return left: ${pointX}px; top: ${pointY}px;},// 隐藏菜单hiddenMenu() {this.activeEle nullthis.isShowDelMenu false},// 删除选中元素handleDeleteMenu() {this.canvas.remove(this.activeEle)this.canvas.requestRenderAll()this.hiddenMenu()}}
}
十六、自由绘画
1、开启绘图模式 let canvas new fabric.Canvas(canvas, {isDrawingMode: true // 开启绘图模式
})
canvas.freeDrawingBrush.color #11999e // 设置画笔颜色
canvas.freeDrawingBrush.width 10 // 设置画笔粗细
canvas.freeDrawingBrush.shadow new fabric.Shadow({ // 设置画笔投影blur: 10,offsetX: 10,offsetY: 10,affectStroke: true,color: #30e3ca
})
2、关闭绘图模式 canvas.isDrawingMode false
十七、绘制背景图片 1、方式一通过img元素添加 img src/assets/images/logo.png idlogolet img document.getElementById(logo)
img.onload () {let canvasImage new fabric.Image(imgElement, {left: 100, // 距离画布左侧距离top: 100, // 距离画布顶部距离width: 200, // 图片宽度height: 200, // 图片高度angle: 50, // 旋转opacity: 1 // 透明度})canvas.add(canvasImage)
}
2、方式二通过图片路径添加 let url http://localhost:82/public/img/logo.png
fabric.Image.fromURL(url, img {let canvasImage img.set({scaleX: 0.5,scaleY: 0.5})canvas.add(canvasImage)
})
十八、绘制文本 Fabric也提供了文本的相关功能Fabric文本允许以面向对象的方式处理文本原生canvas方法只允许在非常低的级别上填充或描边文本通过实例化fabric.Text实例我们就可以使用文本就像我们将使用任何其他Fabric对象移动它缩放它更改其属性等 其次它提供比canvas给我们更丰富的功能包括 Multiline support // 支持多行
Text alignment // 文本对齐 Left、center、right
Text background // 文本背景 背景也遵循文本对齐
Text decoration // 文字装饰 下划线Underline、上划线overline、贯穿线strike-through
Line height // 行高 使用多行文字时出错
Char spacing // 字符间距 使文本更紧凑或间距更大
Subranges // 子范围 将颜色和属性应用于文本对象的子范围
Multibyte // 多字节 支持表情符号
On canvas editing // 交互式画布编辑 可以直接在canvas上键入文本
1、基础用法 let text new fabric.Text(Hello World!, {left: 40,top: 10,fontFamily: Comic Sans, // 字体fontSize: 60, // 字号fontWeight: 600, // 字体重量粗细normal、bold 或 数字100、200、400、600、800fontStyle: normal, // 字体风格 正常 normal 或 斜体 italiccharSpacing: 100, // 字距fill: red, // 字体颜色cornerColor: pink, // 角的颜色被选中时angle: 30, // 旋转backgroundColor: #ffd460, // 背景色borderColor: yellowGreen, // 边框颜色被选中时borderScaleFactor: 4, // 边框粗细被选中时borderDashArray: [10, 4, 20], // 创建边框虚线stroke: #3f72af, // 文字描边颜色蓝色strokeWidth: 2, // 文字描边粗细textAlign: left, // 对齐方式left 左对齐 right 右对齐 center 居中opacity: 0.8, // 不透明度// text: 雷猴, // 文字内容会覆盖之前设置的值selectable: true, // 能否被选中默认trueshadow: rgba(0, 0, 0, 0.5) 5px 5px 5px, // 投影
})
canvas.add(text)
2、文本修饰 // 下划线
let underlineText new fabric.Text(I am an undrline text, {underline: true
})
canvas.add(underlineText)// 贯穿线
let strokeThroughText new fabric.Text(I am a stroke-through text, {linethrough: true,top: 40
})
canvas.add(strokeThroughText)// 上划线
let overlineText new fabric.Text(I am overline text, {overline:true,top: 80
})
canvas.add(overlineText)
3、可编辑文本 let IText new fabric.IText(雷猴啊双击打几个字试下~, {fontFamily: Comic Sans
})
canvas.add(IText)
十九、绘制线和路径
1、绘制直线 let line new fabric.Line([0, 100, 100, 100], {fill: green, // 填充色stroke: green, // 笔触颜色strokeWidth: 2, // 笔触宽度
});
canvas.add(line);
2、绘制虚线 在绘制直线的基础上添加属性strokeDashArray[a,b]表示每隔a个像素空b个像素。 let line new fabric.Line([0, 100, 100, 100], {fill: green, // 填充色stroke: green, // 笔触颜色strokeWidth: 2, // 笔触宽度strokeDashArray:[3,1]
});
canvas.add(line);
3、绘制路径
Fabric.js使用 new fabric.Path 创建路径。M可以理解为新的起始点 xy 坐标L每个折点的 xy 坐标z自动闭合自动把结束点和起始点连接起来 let path new fabric.Path(M 0 0 L 200 100 L 170 200 z)
path.set({top: 120, // 距离容器顶部距离 120pxleft: 120, // 距离容器左侧距离 120pxfill: hotpink, // 填充 亮粉色opacity: 0.5, // 不透明度 50%stroke: black, // 描边颜色 黑色strokeWidth: 10 // 描边粗细 10px
}) 上述代码第一行“M”代表“移动”命令“M 0 0” 代表把画笔移动到0, 0点坐标。“L”代表“线”“L 200 100 ”的意思是使用钢笔画一条线从0, 0坐标画到200, 100坐标。“z” 代表让图形闭合路径。这样就画出了一个三角形。画好三角形后我们可以用set( )方法对三角形的位置、颜色、角度、透明度等属性进行设置。
二十、自由绘制矩形 templatediv classcanvas-box refcanvasBoxcanvas idcanvas/canvasel-button clickhandleActiveRect绘制矩形/el-button/div
/template
script
export default {name: PointerDetail,data () {return {canvas: null,lastPoint: null, // 上次鼠标点位坐标strokeColor: transparent, // 轮廓填充颜色isActiveRect: false, // 是否激活绘制矩形rectList: [] // 绘制的矩形列表}},mounted() {this.init()},methods: {// 初始化init() {this.canvas new fabric.Canvas(canvas, {width: this.$refs.canvasBox.offsetWidth,height: this.$refs.canvasBox.offsetHeight,backgroundColor: #2E3136,selectionColor: transparent,selectionBorderColor: transparent,hoverCursor: default})this.canvas.on(mouse:down, this.onMouseDown)this.canvas.on(mouse:up, this.onMouseUp)this.canvas.on(object:added, this.onObjectAdded)},// 监听鼠标按下事件onMouseDown(opt) {if (this.isActiveRect) {this.lastPoint opt.absolutePointer || nullthis.strokeColor #00FF64}},// 监听鼠标松开事件onMouseUp(opt) {if (this.isActiveRect) {this.drawRect(opt.absolutePointer)}},// 绘制完成元素事件onObjectAdded(opt) {let target opt.targetif (target.stroke #00FF64) {this.isActiveRect this.rectList.push(target)}},// 绘制矩形drawRect(pointer) {if (!this.lastPoint || JSON.stringify(this.lastPoint) JSON.stringify(pointer)) { // 点击事件不生成矩形return}let top Math.min(this.lastPoint.y, pointer.y)let left Math.min(this.lastPoint.x, pointer.x)let width Math.abs(this.lastPoint.x - pointer.x)let height Math.abs(this.lastPoint.y - pointer.y)let rect new fabric.Rect({ top, left,width,height,fill: transparent,stroke: this.strokeColor,selectable: false})this.canvas.add(rect)this.lastPoint nullthis.strokeColor transparent},// 激活绘制矩形handleActiveRect() {this.isActiveRect !this.isActiveRectif(this.isActiveRect) {this.canvas.selectionBorderColor #00FF64}}}
}
二十一、自由绘制圆形 templatediv classcanvas-box refcanvasBoxcanvas idcanvas/canvasel-button clickhandleActiveCircle绘制圆形/el-button/div
/template
script
export default {name: PointerDetail,data () {return {canvas: null,canvasCircle: null,downPoint: null,strokeColor: transparent, // 轮廓填充颜色isActiveCircle: false, // 是否激活绘制圆形circleList: [] // 绘制的圆形列表}},mounted() {this.init()},methods: {// 初始化init() {this.canvas new fabric.Canvas(canvas, {width: this.$refs.canvasBox.offsetWidth,height: this.$refs.canvasBox.offsetHeight,backgroundColor: #2E3136,selectionColor: transparent,selectionBorderColor: transparent,hoverCursor: default})this.canvas.on(mouse:down, this.onMouseDown)this.canvas.on(mouse:move, this.onMouseMove)this.canvas.on(mouse:up, this.onMouseUp)this.canvas.on(object:added, this.onObjectAdded)},// 监听鼠标按下事件onMouseDown(opt) {if (this.isActiveCircle) {this.downPoint opt.absolutePointerthis.strokeColor #00FF64this.canvasCircle new fabric.Circle({top: this.downPoint.y,left: this.downPoint.x,radius: 0,fill: transparent,stroke: this.strokeColor,strokeWidth: 2,selectable: false,})this.canvas.add(this.canvasCircle)}},// 监听鼠标移动事件onMouseMove(opt) {if (this.isActiveCircle this.canvasCircle) {let radius Math.min(Math.abs(this.downPoint.x - opt.absolutePointer.x), Math.abs(this.downPoint.y - opt.absolutePointer.y)) / 2let top opt.absolutePointer.y this.downPoint.y ? this.downPoint.y : this.downPoint.y - radius * 2let left opt.absolutePointer.x this.downPoint.x ? this.downPoint.x : this.downPoint.x - radius * 2this.canvasCircle.set(radius, radius)this.canvasCircle.set(top, top)this.canvasCircle.set(left, left)this.canvas.requestRenderAll()}},// 监听鼠标松开事件onMouseUp(opt) {if (this.isActiveCircle) {if (JSON.stringify(this.downPoint) JSON.stringify(opt.absolutePointer)) {this.canvas.remove(this.canvasCircle)} else {if (this.canvasCircle){this.canvasCircle.set(stroke, this.strokeColor)}}this.canvasCircle null}},// 绘制完成元素事件onObjectAdded(opt) {let target opt.targetif (target.stroke #00FF64) {this.isActiveCircle this.circleList.push(target)}},// 激活绘制圆形handleActiveCircle() {this.isActiveCircle !this.isActiveCircleif(this.isActiveCircle) {this.canvas.selectionBorderColor #00FF64}}}
}
二十二、自由绘制椭圆形 templatediv classcanvas-box refcanvasBoxcanvas idcanvas/canvasel-button clickhandleActiveEllipse绘制椭圆形/el-button/div
/template
script
export default {name: PointerDetail,data () {return {canvas: null,canvasEllipse: null,downPoint: null,strokeColor: transparent, // 轮廓填充颜色isActiveEllipse: false, // 是否激活绘制椭圆形ellipseList: [] // 绘制的椭圆形列表}},mounted() {this.init()},methods: {// 初始化init() {this.canvas new fabric.Canvas(canvas, {width: this.$refs.canvasBox.offsetWidth,height: this.$refs.canvasBox.offsetHeight,backgroundColor: #2E3136,selectionColor: transparent,selectionBorderColor: transparent,hoverCursor: default})this.canvas.on(mouse:down, this.onMouseDown)this.canvas.on(mouse:move, this.onMouseMove)this.canvas.on(mouse:up, this.onMouseUp)this.canvas.on(object:added, this.onObjectAdded)},// 监听鼠标按下事件onMouseDown(opt) {if (this.isActiveEllipse) {this.downPoint opt.absolutePointerthis.strokeColor #00FF64this.canvasEllipse new fabric.Ellipse({top: this.downPoint.y,left: this.downPoint.x,rx: 0,ry: 0,fill: transparent,stroke: this.strokeColor,strokeWidth: 2,selectable: false,})this.canvas.add(this.canvasEllipse)}},// 监听鼠标移动事件onMouseMove(opt) {if (this.isActiveEllipse this.canvasEllipse) {let rx Math.abs(this.downPoint.x - opt.absolutePointer.x) / 2let ry Math.abs(this.downPoint.y - opt.absolutePointer.y) / 2let top opt.absolutePointer.y this.downPoint.y ? this.downPoint.y : this.downPoint.y - ry * 2let left opt.absolutePointer.x this.downPoint.x ? this.downPoint.x : this.downPoint.x - rx * 2this.canvasEllipse.set(rx, rx)this.canvasEllipse.set(ry, ry)this.canvasEllipse.set(top, top)this.canvasEllipse.set(left, left)this.canvas.requestRenderAll()}},// 监听鼠标松开事件onMouseUp(opt) {if (this.isActiveEllipse) {if (JSON.stringify(this.downPoint) JSON.stringify(opt.absolutePointer)) {this.canvas.remove(this.canvasEllipse)} else {if (this.canvasEllipse){this.canvasEllipse.set(stroke, this.strokeColor)}}this.canvasEllipse null}},// 绘制完成元素事件onObjectAdded(opt) {let target opt.targetif (target.stroke #00FF64) {this.isActiveEllipse this.ellipseList.push(target)}},// 激活绘制椭圆形handleActiveEllipse() {this.isActiveEllipse !this.isActiveEllipseif(this.isActiveEllipse) {this.canvas.selectionBorderColor #00FF64}}}
}
二十三、自由绘制三角形 templatediv classcanvas-box refcanvasBoxcanvas idcanvas/canvasel-button clickhandleActiveTriangle绘制三角形/el-button/div
/template
script
export default {name: PointerDetail,data () {return {canvas: null,canvasTriangle: null,downPoint: null,strokeColor: transparent, // 轮廓填充颜色isActiveTriangle: false, // 是否激活绘制三角形triangleList: [] // 绘制的三角形列表}},mounted() {this.init()},methods: {// 初始化init() {this.canvas new fabric.Canvas(canvas, {width: this.$refs.canvasBox.offsetWidth,height: this.$refs.canvasBox.offsetHeight,backgroundColor: #2E3136,selectionColor: transparent,selectionBorderColor: transparent,hoverCursor: default})this.canvas.on(mouse:down, this.onMouseDown)this.canvas.on(mouse:move, this.onMouseMove)this.canvas.on(mouse:up, this.onMouseUp)this.canvas.on(object:added, this.onObjectAdded)},// 监听鼠标按下事件onMouseDown(opt) {if (this.isActiveTriangle) {this.downPoint opt.absolutePointerthis.strokeColor #00FF64this.canvasTriangle new fabric.Triangle({top: this.downPoint.y,left: this.downPoint.x,width: 0,height: 0,fill: transparent,stroke: this.strokeColor,strokeWidth: 2,selectable: false,})this.canvas.add(this.canvasTriangle)}},// 监听鼠标移动事件onMouseMove(opt) {if (this.isActiveTriangle this.canvasTriangle) {let width Math.abs(this.downPoint.x - opt.absolutePointer.x)let height Math.abs(this.downPoint.y - opt.absolutePointer.y)let top opt.absolutePointer.y this.downPoint.y ? this.downPoint.y : opt.absolutePointer.ylet left opt.absolutePointer.x this.downPoint.x ? this.downPoint.x : opt.absolutePointer.xthis.canvasTriangle.set(width, width)this.canvasTriangle.set(height, height)this.canvasTriangle.set(top, top)this.canvasTriangle.set(left, left)this.canvas.requestRenderAll()}},// 监听鼠标松开事件onMouseUp(opt) {if (this.isActiveTriangle) {if (JSON.stringify(this.downPoint) JSON.stringify(opt.absolutePointer)) {this.canvas.remove(this.canvasTriangle)} else {if (this.canvasTriangle){this.canvasTriangle.set(stroke, this.strokeColor)}}this.canvasTriangle null}},// 绘制完成元素事件onObjectAdded(opt) {let target opt.targetif (target.stroke #00FF64) {this.isActiveTriangle this.triangleList.push(target)}},// 激活绘制矩形handleActiveTriangle() {this.isActiveTriangle !this.isActiveTriangleif(this.isActiveTriangle) {this.canvas.selectionBorderColor #00FF64}}}
}
二十四、自由绘制多边形 templatediv classcanvas-box refcanvasBoxcanvas idcanvas/canvasel-button clickhandleActivePolygon绘制多边形/el-button/div
/template
script
export default {name: PointerDetail,data () {return {canvas: null,canvasPolygon: null,strokeColor: transparent, // 轮廓填充颜色isActivePolygon: false, // 是否激活绘制多边形polygonList: [] // 绘制的多边形列表}},mounted() {this.init()},methods: {// 初始化init() {this.canvas new fabric.Canvas(canvas, {width: this.$refs.canvasBox.offsetWidth,height: this.$refs.canvasBox.offsetHeight,backgroundColor: #2E3136,selectionColor: transparent,selectionBorderColor: transparent,hoverCursor: default})this.canvas.on(mouse:down, this.onMouseDown)this.canvas.on(mouse:move, this.onMouseMove)this.canvas.on(mouse:dblclick, this.onDblclick)this.canvas.on(object:added, this.onObjectAdded)},// 监听鼠标按下事件onMouseDown(opt) {if (this.isActivePolygon) {this.strokeColor #00FF64if (this.canvasPolygon null) {this.createPolygon(opt)} else {this.changeCurrentPolygon(opt)}}},// 监听鼠标移动事件onMouseMove(opt) {if (this.isActivePolygon this.canvasPolygon) {this.changePolygonBelt(opt)}},// 鼠标双击事件onDblclick(opt) {this.finishPolygon(opt)},// 绘制完成元素事件onObjectAdded(opt) {let target opt.targetif (target.stroke #00FF64) {this.isActivePolygon this.polygonList.push(target)}},// 创建多边形createPolygon(opt) {this.canvasPolygon new fabric.Polygon([{ x: opt.absolutePointer.x, y: opt.absolutePointer.y },{ x: opt.absolutePointer.x, y: opt.absolutePointer.y }], {fill: transparent,stroke: this.strokeColor,objectCaching: false})this.canvas.add(this.canvasPolygon)},// 修改当前正在创建的多边形changeCurrentPolygon(opt) {let points this.canvasPolygon.pointspoints.push({x: opt.absolutePointer.x,y: opt.absolutePointer.y})this.canvas.requestRenderAll()},// 多边形橡皮带changePolygonBelt(opt) {let points this.canvasPolygon.pointspoints[points.length - 1].x opt.absolutePointer.xpoints[points.length - 1].y opt.absolutePointer.ythis.canvas.requestRenderAll()},// 完成多边形绘制finishPolygon(opt) {let points this.canvasPolygon.pointspoints[points.length - 1].x opt.absolutePointer.xpoints[points.length - 1].y opt.absolutePointer.ypoints.pop()points.pop()this.canvas.remove(this.canvasPolygon)if (points.length 2) {let polygon new fabric.Polygon(points, {stroke: this.strokeColor,fill: transparent,selectable: false})this.canvas.add(polygon)} else {this.$message.warning(标记框小于最小标定像素)}this.canvasPolygon nullthis.canvas.requestRenderAll()this.strokeColor transparent},// 激活绘制多边形handleActivePolygon() {this.isActivePolygon !this.isActivePolygonif(this.isActivePolygon) {this.canvas.selectionBorderColor #00FF64}}}
}