相关文章推荐
温柔的沙滩裤  ·  apache 2.4 ...·  2 年前    · 
玩篮球的佛珠  ·  JQuery ...·  2 年前    · 

Fabric.js 是一个功能强大且简单的 HTML5 画布库,它给 canvas 上的元素提供了交互式对象模型。借助 Fabric.js ,你可以轻松地绘制各种图形线条图片,对它们进行拖拽、旋转、形变等操作,并且支持丰富的事件方法。

绘制图形

所有的绘制开始之前你需要先创建画布对象:

1
<canvas id="canvas" width="600" height="600"></canvas>
1
var canvas = new fabric.Canvas('canvas')

绘制圆形

1
2
3
4
5
6
7
8
9
const circle = new fabric.Circle({
radius: 100,
left: 10,
top: 10,
fill: 'yellow',
strokeWidth: 2,
stroke: "red"
})
canvas.add(circle)

绘制矩形

1
2
3
4
5
6
7
8
9
10
const rect = new fabric.Rect({
width: 200,
height: 100,
rx: 20, // 圆角半径(x轴方向)
ry: 20, // 圆角半径(y轴方向)
fill: '#FF4D4F',
strokeWidth: 2,
stroke: "#dedede"
})
canvas.add(rect)

利用 rx ry 这两个圆角属性你也可以通过 fabric.Rect 绘制圆形和椭圆形。

绘制三角形

1
2
3
4
5
6
7
8
const triangle = new fabric.Triangle({
width: 200,
height: 300,
fill: '#FF4D4F',
strokeWidth: 2,
stroke: "#dedede"
})
canvas.add(triangle)

画线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const canvas = new fabric.Canvas('c')
const grid = 30
const lineStroke = '#C5C9CB'
for (let i = 0; i < (canvas.width / grid); i++) {
const lineX = new fabric.Line([ 0, i * grid, canvas.width, i * grid], {
stroke: lineStroke,
selectable: false,
type: 'line'
})
const lineY = new fabric.Line([ i * grid, 0, i * grid, canvas.width], {
stroke: lineStroke,
selectable: false,
type: 'line'
})
canvas.add(lineX)
canvas.add(lineY)
}

fabric.Line([50, 100, 200, 200] 的四个数值分别对应线起点和终点的横纵坐标,利用 Line 类我们可以实现网格线的绘制。 selectable 属性值为 false 的时候表示对象不可选中, type 属性可以自定义对象类型。

添加文字

1
2
3
4
5
6
7
8
9
10
11
12
const text = new fabric.IText('blackstar', {
top: 100,
left: 100,
fontFamily: 'Calibri',
fontSize: 18,
angle: 45,
originX: 'center',
originY: 'center',
centeredRotation: true,
fill: '#000'
})
canvas.add(text)

注意文字内容必须为 字符串 类型,否则会报错。

绘制图片

1
2
3
4
fabric.Image.fromURL('https://s2.ax1x.com/2019/08/18/mlm0Jg.jpg', function(oImg) {
oImg.scale(0.5)
canvas.add(oImg)
})

image scale() 方法用于控制对象的缩放。

群组绘图

群组是 Fabric.js 最强大的功能之一。试想一下,如果你需要在一个方框中添加一些文字你该怎么做?先添加一个矩形,再把文字覆盖在上面吗? Fabric.js 提供了 Group 类帮助我们将多个对象组成一个对象。像上面提到的需求我们就可以这样来实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const rect = new fabric.Rect({
width: 200,
height: 100,
rx: 20,
ry: 20,
fill: '#FF4D4F'
})
const text = new fabric.IText('blackstar', {
fontFamily: 'Calibri',
fontSize: 18,
left: rect.width/2,
top: rect.height/2,
originX: 'center',
originY: 'center',
centeredRotation: true,
fill: '#fff'
})
const block = new fabric.Group([rect,text], {
left: 50,
top: 50
})
canvas.add(block)

Group 类接受对象数组将其组装在一个对象中,排在后面的绘制在上层。

文字垂直水平居中

在群组中设置文字垂直水平居中其实很简单,只需要将文字的坐标中心点通过 originX originY 设置在正中央,横纵坐标分别设置为包裹区域宽高的一半就可以了。

对象属性汇总

常用的有以下几个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 对象移动监听
canvas.on('object:moving', function(e) {
console.log(e.target)
})
// 对象缩放监听
canvas.on('object:scaling', function(e) {
console.log(e.target)
})
// 对象旋转监听
canvas.on('object:rotating', function (e) {
console.log(e.target)
})
// 对象变动监听,包括位置、大小、角度等变化的监听
canvas.on('object:modified', function(e) {
console.log(e.target)
})
// 点击事件监听
canvas.on('mouse:down', function (e) {
console.log(e.target)
})
canvas.on('mouse:up', function (e) {
console.log(e.target)
})

边界检测

在操作画布上的实例对象时我们并不希望它们超出画布的范围,那么就需要进行边界判断,控制对象不要越过指定区域。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
canvas.on('object:moving', function (e) {
checkBoudningBox(e)
})
canvas.on('object:rotating', function (e) {
checkBoudningBox(e)
})
canvas.on('object:scaling', function (e) {
checkBoudningBox(e)
})
// 此为对象坐标原点设置在中心的情况
function checkBoudningBox(e) {
const obj = e.target

if (!obj) {
return
}
obj.setCoords()

const objBoundingBox = obj.getBoundingRect()
if (objBoundingBox.top < 0) {
obj.set('top', objBoundingBox.height/2)
obj.setCoords()
}
if (objBoundingBox.left > canvas.width - objBoundingBox.width) {
obj.set('left', canvas.width - objBoundingBox.width/2)
obj.setCoords()
}
if (objBoundingBox.top > canvas.height - objBoundingBox.height) {
obj.set('top', canvas.height - objBoundingBox.height/2)
obj.setCoords()
}
if (objBoundingBox.left < 0) {
obj.set('left', objBoundingBox.width/2)
obj.setCoords()
}
}

原理就是利用事件监听和对象边界矩形的顶点坐标,当坐标值超出画布范围时重置对象坐标。