需要绘制一条可控制的贝塞尔曲线,发现fabic官网中一个demo有点类似。感兴趣的可以移步官网查看demo。
官网的demo是对于html 而言的,放在vue中需要变换一下,具体代码如下:
<template><div class="dashboard-container" @contextmenu.prevent><canvas id="editorCanvas" ref="canvas" style="margin-top: 10px;" /></div>
</template><script>
import { mapGetters } from 'vuex'
// import fabric from 'fabric'
let canvas = ''
export default {name: 'Dashboard',computed: {...mapGetters(['name'])},data () {return {width: window.innerWidth,height: window.innerHeight,activeEl: {}// 获取当前点击元素}},mounted () {const self = this// canvas = new fabric.StaticCanvas('editorCanvas', {//静态画布,不可以修改canvas = new fabric.Canvas('editorCanvas', {width: self.width,height: self.height,backgroundColor: '#ffffff'})var line = new fabric.Path('M 65 0 Q 100, 100, 200, 0', { fill: '', stroke: 'black', objectCaching: false })line.path[0][1] = 100line.path[0][2] = 100line.path[1][1] = 200line.path[1][2] = 200line.path[1][3] = 300line.path[1][4] = 100line.selectable = falsecanvas.add(line)var p1 = self.makeCurvePoint(200, 200, null, line, null)p1.name = 'p1'canvas.add(p1)var p0 = self.makeCurveCircle(100, 100, line, p1, null)p0.name = 'p0'canvas.add(p0)var p2 = self.makeCurveCircle(300, 100, null, p1, line)p2.name = 'p2'canvas.add(p2)canvas.on('object:selected', function (opt) {self.onObjectSelected(opt)})canvas.on('object:moving', function (opt) {self.onObjectMoving(opt)})canvas.on('selection:cleared', function (opt) {self.onSelectionCleared(opt)// canvas.on({// 'object:selected': this.onObjectSelected(e),// 'object:moving': this.onObjectMoving(e),// 'selection:cleared': this.onSelectionCleared(e)})},methods: {makeCurveCircle (left, top, line1, line2, line3) {var c = new fabric.Circle({left: left,top: top,strokeWidth: 5,radius: 12,fill: '#fff',stroke: '#666',originX: 'center',originY: 'center'})c.hasBorders = c.hasControls = falsec.line1 = line1c.line2 = line2c.line3 = line3return c},makeCurvePoint (left, top, line1, line2, line3) {var c = new fabric.Circle({left: left,top: top,strokeWidth: 8,originX: 'center',originY: 'center',radius: 14,fill: '#fff',stroke: '#666'})c.hasBorders = c.hasControls = falsec.line1 = line1c.line2 = line2c.line3 = line3return c},onObjectSelected (e) {// console.log(e.target)var activeObject = e.targetif (activeObject.name == 'p0' || activeObject.name == 'p2') {activeObject.line2.animate('opacity', '1', {duration: 200,onChange: canvas.renderAll.bind(canvas)})activeObject.line2.selectable = true}},onSelectionCleared (e) {var activeObject = e.targetif (activeObject.name == 'p0' || activeObject.name == 'p2') {activeObject.line2.animate('opacity', '0', {duration: 200,onChange: canvas.renderAll.bind(canvas)})activeObject.line2.selectable = false} else if (activeObject.name == 'p1') {activeObject.animate('opacity', '0', {duration: 200,onChange: canvas.renderAll.bind(canvas)})activeObject.selectable = false}},onObjectMoving (e) {if (e.target.name == 'p0' || e.target.name == 'p2') {var p = e.targetif (p.line1) {p.line1.path[0][1] = p.leftp.line1.path[0][2] = p.top} else if (p.line3) {p.line3.path[1][3] = p.leftp.line3.path[1][4] = p.top}} else if (e.target.name == 'p1') {var p = e.targetif (p.line2) {p.line2.path[1][1] = p.leftp.line2.path[1][2] = p.top}} else if (e.target.name == 'p0' || e.target.name == 'p2') {var p = e.targetp.line1 && p.line1.set({ 'x2': p.left, 'y2': p.top })p.line2 && p.line2.set({ 'x1': p.left, 'y1': p.top })p.line3 && p.line3.set({ 'x1': p.left, 'y1': p.top })p.line4 && p.line4.set({ 'x1': p.left, 'y1': p.top })}}}
}
</script><style lang="scss" scoped>
</style>
效果如图:
核心:定义 line时,设置path数组值。变换时修改path数组中的值。直接=
但是我需要绘制三阶贝塞尔曲线,即要两个控制点。这时候就需要变形一下。
const line = new fabric.Path(`M ${item1.left} ${item1.top} C ${item1.left} ${item2.top}, ${item2.left} ${item1.top}, ${item2.left}, ${item2.top}`, {
....../* 起点 */line.path[0][1] = item1.leftline.path[0][2] = item1.top/* 控制点1 */line.path[1][1] = item1.leftline.path[1][2] = item2.top/* 控制点1 */line.path[1][3] = item2.leftline.path[1][4] = item1.top/* 结束点 */line.path[1][5] = item2.leftline.path[1][6] = item2.top
修改直接进行重新赋值。