乐趣区

关于前端:Fabricjs-自定义子类

本文简介

点赞 + 关注 + 珍藏 = 学会了

fabric.js 在出厂时就提供了几个根底图形,比方矩形、圆形、三角形等。

但这些图形可能不能满足日常开发,咱们可能还须要一些自定义的图形。

我做了个 自定义半圆 的 demo,聊聊如何创立自定义图形。

尽管 fabric.js 提供了非常简单的办法创立自定义子类,但如果须要创立简单的图形,还是须要有肯定 canvas 根底的。

如果你还不太熟悉原生 canvas,举荐浏览《Canvas 从入门到劝敌人放弃(图解版)》

本文所有案例都默认引入了 fabric.js,所以不会在每段代码里反复引入了。

什么是 fabric.js 的子类?

fabric.js 类的概念其实和原生 jsclass 差不多。

fabric.js 中,能够创立类,能够继承类。

比方在 官网例子 中,继承 矩形 创立进去的一个带文本的类。它领有矩形元素的所有属性和办法,同时还增加了 label 属性,能够在矩形中增加文本标签。

fabric.js 如何创立类?

文档:fabric.util.createClass

fabric.js 中创立类,能够应用 fabric.util.createClass() 办法。

这里借用官网的 demo 进行解说。

let Point = fabric.util.createClass({initialize: function(x, y) {
    this.x = x || 0
    this.y = y || 0
  },
  toString: function() {return `${this.x}/${this.y}`
  }
})

fabric.util.createClass 承受一个对象参数,并基于该对象的配置创立一个“类”。

须要注意的是 initialize 属性,initialize 的值是一个办法,用于初始化。有点相似原生 jsclass constructor 。留神,是 相似

initialize 中接管实例化时传进来的参数。

let point = new Point(10, 20)

console.log(point.x) // 10
console.log(point.y) // 20

console.log(point.toString()) // "10/20"

子类的继承

在创立类时,只需在 fabric.util.createClass 中传入 1 个对象即可。

如果创立子类时须要继承某个父类,则要在 fabric.util.createClass 中传入 2 个参数。

fabric.util.createClass(parentopt, propertiesopt)

  • parentopt: 父类
  • propertiesopt 创立子类的对象(和后面创立类的对象一样)

还是 官网例子。

在后面的创立类时,咱们创立了一个 Point 的类,这个类只承受 xy 属性;外部还有一个 toString() 办法。

如果咱们想在 Point 类的根底上再创立一个 ColoredPoint 类(也就是 ColoredPoint 继承 Point),能够这样写。

let ColoredPoint = fabric.util.createClass(
  // 参数 1:父类
  Point,
  // 参数 2:子类
  {initialize: function(x, y, color) {this.callSuper('initialize', x, y) // 传给父类的
      this.color = color || '#000' // 新增的 color 属性
    }
  }
)

此时 ColoredPoint 就继承了 Point,并在 Point 的根底上多了 color 属性了。

let redPoint = new ColoredPoint(15, 33, '#f55')
console.log(redPoint.x) // 15
console.log(redPoint.y) // 33
console.log(redPoint.color) // "#f55"
console.log(redPoint.toString()) // "15/33"

Point 里有 toString() 办法,redPoint.toString() 会先 ColoredPoint 找,找不到就从 Point 找。一层层往上找。

如果在 ColoredPoint 中又定义了 toString() 办法,就会笼罩 Point 里定义的。

// 省略局部代码

// 父类
let Point = new fabric.util.createClass({initialize(x, y) {...},
  toString() {return this.x + '/' + this.y}
})

// 子类
let ColoredPoint = fabric.util.createClass(
  // 参数 1:父类
  Point,
  // 参数 2:子类
  {initialize(x, y, color) {...},
    toString() {return '雷猴'}
  }
)

// 实例化
let redPoint = new ColoredPoint(15, 33, '#f55')

console.log(redPoint.toString()) // "雷猴"

如果在子类中想 继承父类的办法 能够应用 callSuper

// 父类
let Point = new fabric.util.createClass({...})

// 省略局部代码
let ColoredPoint = fabric.util.createClass(
  // 参数 1:父类
  Point,
  // 参数 2:子类
  {initialize(x, y, color) {...},
    toString() {return this.callSuper('toString')
    }
  }
)

// let redPoint = new ColoredPoint(15, 33, '#f55')

console.log(redPoint.toString()) // "15/33"

还能够二次包装

// 省略局部代码

// ColoredPoint 的,省略局部代码
toString() {return '从子类 ColoredPoint 调用:' + this.callSuper('toString')
}

// 输入 redPoint 的,省略局部代码
console.log(redPoint.toString()) // 从子类 ColoredPoint 调用: 15/33

继承 fabric.js 自带的图形

在官网案例中实现了这么一个成果。

上图的成果是一个继承了矩形的子类。

矩形是 fabric.js 默认提供的图形对象之一,继承矩形时只需把矩形当做 fabric.util.createClass 的第一个参数即可,而后再增加自定义性能。

// 省略局部代码

// 创立带标签性能的矩形
const LabeledRect = fabric.util.createClass(
  // 要继承的是 fabric 的矩形
  fabric.Rect,
  {
    type: 'labeledRect', // 增加一个 type 属性
    // 初始化
    initialize: function(options) {options || (options = {}) // 初始化参数,免得报错
      this.callSuper('initialize', options) // 继承
      this.set('label', options.label || '') // 设置 label,默认值是空
      this.set({width: 100, height: 50}) // 设置默认宽高
    },
    toObject: function() {
      return fabric.util.object.extend(this.callSuper('toObject'),
        {label: this.get('label')
        }
      )
    },
    // 增加渲染时的操作
    _render: function(ctx) {this.callSuper('_render', ctx)
      ctx.font = this.labelFont || '20px Helevtica'
      ctx.fillStyle = this.labelFill || '#333'
      // 将 label 渲染进去
      ctx.fillText(
        this.label,
        -this.width / 2,
        -this.height / 2 + 20
      )
    }
  }
)

// 创立标签矩形
let labeledRect = new LabeledRect({
  // width: 100,
  // height: 50,
  left: 100,
  top: 100,
  label: 'test',
  fill: '#faa'
})

// 将标签矩形增加到画布中
canvas.add(labeledRect)

因为继承的是矩形,所以还能够应用 fabric.Rect 的属性和办法。

// 省略局部代码

labeledRect.set({
  label: 'trololo',
  fill: '#faf',
  rx: 10,
  ry: 10
})

rxry 都是 fabric.Rect 的属性,能够设置圆角。

创立自定义子类

fabric.js 中的 矩形 Rect三角形 Triangl圆形 Circle 等图形元素都是继承 fabric.Object 的。

通过继承 fabric.Object 创立进去的元素对象,默认是有管制柄之类的货色。

接下来要创立的“半圆”元素也是继承 fabric.Object,这是 fabric.js 提供的一个十分便当的对象。

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  // 创立画布
  let canvas = new fabric.Canvas('c')

  // 创立半圆对象,继承 fabric.Object
  let Semicircle = fabric.util.createClass(fabric.Object, {
    // 初始化
    initialize(options) {this.callSuper('initialize', options)
      this.width = 100
      this.height = 50
    },
    // 渲染
    _render(ctx) 
      ctx.strokeStyle = this.stroke || '#333' // 初始化描边色彩
      ctx.lineWidth = this.strokeWidth || 1 // 初始化描边宽度
      ctx.fillStyle = this.fill || '#333' // 初始化填充色
      ctx.beginPath() // 开始绘制门路
      ctx.arc(0, -25, 50, 0, 180 * Math.PI / 180) // 绘制半圆
      ctx.closePath() // 完结绘制门路
      ctx.stroke() // 描边
      ctx.fill() // 填充}
  })

  // 创立一个半圆
  let semicircle = new Semicircle({
    top: 10,
    left: 10,
    stroke: '#7bcfa6', // 描边色
    fill: '#ed5736', // 填充色
    strokeWidth: 10 // 描边宽度
  })

  // 将半圆增加到画布里
  canvas.add(semicircle)
</script>

_render 提供了 ctx 参数,这个参数是 canvas 提供的一个 context 对象。通过该对象能够发明不同图形,这是 canvas 的基础知识,也是 fabric.js 创立子类时必须把握的常识。

如果对 canvas 还不太纯熟的话,能够看看《Canvas 从入门到劝敌人放弃(图解版)》

如果你不喜爱将子类定义成一个变量,也能够把子类绑在 fabric 上。

fabric.Semicircle = fabric.util.createClass(...)

// 创立一个半圆
let semicircle = new fabric.Semicircle(...)

尽管这么做看上去和创立矩形、圆形等图形的写法差不多,但我还是不太倡议这么做。

因为有可能一不小心就跟 fabric 的某个属性重名,有可能就被你笼罩了本来的办法。

所以还是将子类保留到独立的变量中比拟稳。

代码仓库

⭐创立子类 createClass

举荐浏览

👍《Fabric.js 从入门到_ _ _ _》

👍《Fabric.js 管制元素层级》

👍《Fabric.js 动静设置字号大小》

👍《Fabric.js 激活输入框》

👍《Fabric.js 自定义选框款式》

👍《Fabric.js 元素核心缩放》

点赞 + 关注 + 珍藏 = 学会了
代码仓库

退出移动版