以前使用这个框架写过一个卡片DIY的项目,中间遇到不少问题都只能经过google或github issues才能解决,国内资料较少,因此才想写这篇文章来简单的作下总结,但愿能够帮到其余人哈。javascript
附上我的项目地址:vue-card-diy 欢迎star~ ✨html
Fabric.js 是一个强大的H5 canvas框架,在原生canvas之上提供了交互式对象模型,经过简洁的api就能够在画布上进行丰富的操做。vue
该框架是个开源项目,项目地址: githubjava
使用Fabric.js,你能够在画布上建立和填充对象; 好比简单的几何形状 - 矩形,圆形,椭圆形,多边形,自定义图片或由数百或数千个简单路径组成的更复杂的形状。 另外,还可使用鼠标缩放,移动和旋转这些对象; 修改它们的属性 - 颜色,透明度,z-index等。也能够将画布上的对象进行组合。下面我将会介绍我经常使用的功能以及场景,更多功能能够参考 官方文档git
npm install fabric --save
复制代码
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>
复制代码
首先在html页面中写一个350 x 200的canvas标签, 这里不写宽高也行,后面能够经过js来设置宽高github
<canvas id="canvas" width="350" height="200"></canvas>
复制代码
初始化fabric的canvas对象,建立一个卡片(后面都用card
表示画布对象)ajax
const card = new fabric.Canvas('canvas')
// ...这里能够写canvas对象的一些配置,后面将会介绍
// 若是<canvas>标签没设置宽高,能够经过js动态设置
card.setWidth(350)
card.setHeight(200)
复制代码
就是这么简单,这样就建立了一个基本的画布。npm
官方提供了不少事件,如下为经常使用的事件:json
object:added
添加图层object:modified
编辑图层object:removed
移除图层selection:created
初次选中图层selection:updated
图层选择变化selection:cleared
清空图层选中// 在canvas对象初始化后,经过如下方式监听
// 好比监听画布的图层编辑事件
card.on('object:modified', (e) => {
console.log(e.target) // e.target为当前编辑的Object
// ...旋转,缩放,移动等编辑图层的操做都监听到
// 因此若是有撤销/恢复的场景,这里能够保存编辑状态
});
复制代码
// 读取图片地址,设置画布背景
fabric.Image.fromURL('xx/xx/bg.jpg', (img) => {
img.set({
// 经过scale来设置图片大小,这里设置和画布同样大
scaleX: card.width / img.width,
scaleY: card.height / img.height,
});
// 设置背景
card.setBackgroundImage(img, card.renderAll.bind(card));
card.renderAll();
});
复制代码
若是要设置画布的背景颜色,能够在canvas初始化时设置canvas
const card = new fabric.Canvas('canvas', {
backgroundColor: 'blue' // 画布背景色为蓝色
});
// 或者
card.backgroundColor = 'blue';
// 或者
card.setBackgroundColor('blue');
复制代码
fabric.js提供了不少对象,除了基本的 Rect
,Circle
,Line
,Ellipse
,Polygon
,Polyline
,Triangle
对象外,还有如 Image
,Textbox
,Group
等更高级的对象,这些都是继承自Fabric的Object对象。
下面我就介绍如何添加图片和文字,其余对象大同小异
/** * 如何向画布添加一个Image对象? */
// 方式一(经过img元素添加)
const imgElement = document.getElementById('my-image');
const imgInstance = new fabric.Image(imgElement, {
left: 100, // 图片相对画布的左侧距离
top: 100, // 图片相对画布的顶部距离
angle: 30, // 图片旋转角度
opacity: 0.85, // 图片透明度
// 这里能够经过scaleX和scaleY来设置图片绘制后的大小,这里为原来大小的一半
scaleX: 0.5,
scaleY: 0.5
});
// 添加对象后, 以下图
card.add(imgInstance);
复制代码
// 方式二(经过图片路径添加)
fabric.Image.fromURL('xx/xx/vue-logo.png', (img) => {
img.set({
hasControls: false, // 是否开启图层的控件
borderColor: 'orange', // 图层控件边框的颜色
});
// 添加对象后, 以下图
canvas.add(img);
});
复制代码
/** * 如何向画布添加一个Textbox对象? */
const textbox = new fabric.Textbox('这是一段文字', {
left: 50,
top: 50,
width: 150,
fontSize: 20, // 字体大小
fontWeight: 800, // 字体粗细
// fill: 'red', // 字体颜色
// fontStyle: 'italic', // 斜体
// fontFamily: 'Delicious', // 设置字体
// stroke: 'green', // 描边颜色
// strokeWidth: 3, // 描边宽度
hasControls: false,
borderColor: 'orange',
editingBorderColor: 'blue' // 点击文字进入编辑状态时的边框颜色
});
// 添加文字后,以下图
card.add(textbox);
复制代码
// 方式一
this.selectedObj = card.getActiveObject(); // 返回当前画布中被选中的图层
// 方式二
card.on('selection:created', (e) => {
// 选中图层事件触发时,动态更新赋值
this.selectedObj = e.target
})
复制代码
// 顺时针90°旋转
const currAngle = this.selectedObj.angle; // 当前图层的角度
const angle = currAngle === 360 ? 90 :currAngle + 90;
this.selectedObj.rotate(angle);
// 若是是经过滑块的方式控制旋转
// this.selectedObj.rotate(slideValue);
// 全部图层的操做以后,都须要调用这个方法
card.renderAll()
复制代码
// 水平翻转,同理垂直翻转改成scaleY属性
this.selectedObj.set({
scaleX: -this.selectedObj.scaleX,
})
card.renderAll()
复制代码
card.remove(this.selectedObj) // 传入须要移除的object
card.renderAll()
复制代码
向画布添加图层,默认是依次往上叠加,可是当你选中一个图层进入active
状态时,该图层会默认置于顶层,若是像禁止选中图层时指定,能够:
// 在画布初始化后设置
card.preserveObjectStacking = true // 禁止选中图层时自定置于顶部
复制代码
设置以后,我选中vue logo就是这个样子,不会置顶。
// 上移图层
this.selectedObj.bringForward();
// 下移图层
this.selectedObj.sendBackwards();
// 也可使用canvas对象的moveTo方法,移至图层到指定位置
card.moveTo(object, index);
复制代码
框架提供了如 toJSON
和 loadFromJSON
方法,做用分别为导出当前画布的json信息,加载json画布信息来还原画布状态。
// 导出当前画布信息
const currState = card.toJSON(); // 导出的Json以下图
复制代码
// 加载画布信息
card.loadFromJSON(lastState, () => {
card.renderAll();
});
复制代码
const dataURL = card.toDataURL({
format: 'jpeg', // jpeg或png
quality: 0.8 // 图片质量,仅jpeg时可用
// 截取指定位置和大小
//left: 100,
//top: 100,
//width: 200,
//height: 200
});
复制代码
如转载本文请注明文章做者及出处!