需要绘制一条可控制的贝塞尔曲线,发现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] = 100
    line.path[0][2] = 100
    line.path[1][1] = 200
    line.path[1][2] = 200
    line.path[1][3] = 300
    line.path[1][4] = 100
    line.selectable = false
    canvas.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 = false
      c.line1 = line1
      c.line2 = line2
      c.line3 = line3
      return 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 = false
      c.line1 = line1
      c.line2 = line2
      c.line3 = line3
      return c
    },
    onObjectSelected (e) {
      // console.log(e.target)
      var activeObject = e.target
      if (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.target
      if (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.target
        if (p.line1) {
          p.line1.path[0][1] = p.left
          p.line1.path[0][2] = p.top
        } else if (p.line3) {
          p.line3.path[1][3] = p.left
          p.line3.path[1][4] = p.top
        }
      } else if (e.target.name == 'p1') {
        var p = e.target
        if (p.line2) {
          p.line2.path[1][1] = p.left
          p.line2.path[1][2] = p.top
        }
      } else if (e.target.name == 'p0' || e.target.name == 'p2') {
        var p = e.target
        p.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.left
        line.path[0][2] = item1.top
        /* 控制点1 */
        line.path[1][1] = item1.left
        line.path[1][2] = item2.top
        /* 控制点1 */
        line.path[1][3] = item2.left
        line.path[1][4] = item1.top
        /* 结束点 */
        line.path[1][5] = item2.left
        line.path[1][6] = item2.top
修改直接进行重新赋值。




![【pytest】 pytest拓展功能 pycharm PermissionError: [Errno 13] Permission denied:](https://img-blog.csdnimg.cn/0042fe0bbb6541c9a016359e01c26b2b.png)














