fabic.js Quadratic Curve /可控制的曲线

需要绘制一条可控制的贝塞尔曲线,发现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
        /* 控制点2 */
        line.path[1][3] = item2.left
        line.path[1][4] = item1.top
        /* 结束点 */
        line.path[1][5] = item2.left
        line.path[1][6] = item2.top

修改直接进行重新赋值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值