转载请保留这部分内容,注明出处。
关注公众号“头号前端”,每周新鲜前端好文推送。另外,头条号前端团队非常 期待你的加入
简介
fabricjs 在国内并不算特别出名,但是在国外应该是特别的火了。它是一个强大的js库,使用它能够很方便的操作canvas。平时使用canvas的时候,总要学习它的各个api,画简单图形还算熟练,一旦稍微复杂一点就需要不断的查文档,非常不方便。fabric.js提供在上面建立元素、编辑图形和文本、对svg和json格式的序列化和反序列化、对元素进行事件响应等等功能。fabricjs是一个完全开源的项目,由麻省理工学院授权,多年来一直发光发热。
整体结构
使用
npm install fabric
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>
对象操作
html的body中存在一个如下的canvas元素,获取这个元素fabric对象:var canvas = new fabric.Canvas( 'main' )
;
<canvas width="800" height="800" id="main"></canvas>
简单图形
在canvas上画矩形:
var rect = new fabric.Rect({
left: 100,
top: 100,
fill: '#f0f',
width: 30,
height: 30
})
canvas.add(rect);
如果使用原生canvas api创建矩形,则会是:
var ele = document.getElementById('main');
var ctx = canvasEl.getContext('2d');
ctx.fillStyle = '#f0f';
ctx.fillRect(100, 100, 30, 30);
虽然代码量差不多,但是fabric可以是的图形对象化,在之后还可以继续操作这个对象,如果想要获取rect的属性,只需要 rect.get('')
,或者想要添加其他的属性,可以使用 rect.set
,如果想要从canvas上删除这个rect,只需要 canvas.remove(rect)
。 在canvas上画圆形:
var circle = new fabric.Circle({
radius: 50,
fill: "#fcb",
left: 200,
top: 100,
})
在canvas上画三角形:
var trigle = new fabric.Triangle({
fill: "#fcb",
left: 300,
top: 100,
height: 100,
width: 80,
})
图片
如果页面中存在img元素: <img src="./d2.png" id="img-d2" style="display: none;">
,那么要将这个元素加载到canvas中:
var imgEle = document.getElementById('img-d2');
var imgInstance = new fabric.Image(imgEle, {
left: 100,
top: 100,
width: 200,
height: 200,
angle: 30
})
canvas.add(imgInstance);
这个img元素如果是用于显示在页面中还好,如果只是为了给fabric添加图片素材,加一个这样的img元素会显得有点多余。fabric还提供了根据url创建图片对象的方法:
fabric.Image.fromURL('./d2.png', function(img){
console.log(img);
// img.scale(0.5);
canvas.add(img);
}, {
left: 100,
top: 100,
width: 200,
height: 200,
angle: 30 //旋转
})
创建图片之后也可以对图片对象进行操作,平常我们使用图片用于背景或者突出一个显示效果,那么可以这么使用: 背景图
canvas.setBackgroundImage('./d2.png', canvas.renderAll.bind(canvas));
也可以多个图片叠加使用作为背景图,在上面代码的基础上设置:
canvas.setOverlayImage('../assets/d1.png', canvas.renderAll.bind(canvas));
显示效果: 对图片进行添加滤镜:
原图
// 添加过滤器,滤镜效果是一个数组,可以添加多个
img.filters.push(new fabric.Image.filters.Grayscale(), new fabric.Image.filters.Invert());
// 应用过滤器并重新渲染画布执行
img.applyFilters(img.filters);
滤镜效果图
更多的滤镜效果可以通过查文档获得,至于图片对象的缩放、旋转之类的效果可以通过设置它的属性获得,比如设置旋转60度 img.set('angle', 60)
。
不规则图形
在canvas上画不规则图形:
var path = new fabric.Path('M 0 0 L 200 100 L 170 200 z');
path.set({
left: 120,
top: 120,
fill: "#4040fe"
})
对于在canvas上画不规则路径或者图形,“M”表示“move”命令,在这个例子中意味着从 0,0
始。“L”代表“直线”,让钢笔画一条直线到 200,100
。另一个“L”创建一条到 177,200
的线 “z”指示绘图笔关闭当前路径并最终确定形状。同样它也可使用set来设置它的其他属性,达到更多的效果:path.set({ fill: 'red', stroke: 'green', opacity: 0.5 });
除了上面的M、L之类还可以用C,C表示贝赛尔曲线,它的作用是画出曲线, var
path = new fabric.Path('M 0 0 L 200 100 L 170 200 C36.67,0,29.5,3.22,24.31,8.41 Z');
但是使用自己去设置点,得到想要的不规则是非常困难的。fabric提供了加载svg来代替这种方式进行实现, loadSVGFromString
或者 loadSVGFromURL
方法来加载SVG文件,让Fabric的SVG解析器来遍历所有SVG元素并创建相应的Path对象。
fabric.loadSVGFromURL('./tab.svg', function(objects){
var SVG = fabric.util.groupSVGElements(objects);
canvas.add(SVG).centerObject(SVG).renderAll();
SVG.setCoords();
})
颜色
fabric提供了很方便的方式创建颜色,这些颜色都可以创建的图形中去:
var col1 = new fabric.Color('#f55');
var col2 = new fabric.Color('#123123');
var col3 = new fabric.Color('356735');
var col4 = new fabric.Color('rgb(100,0,100)');
var col5 = new fabric.Color('rgba(10, 20, 30, 0.5)');
rgb和hex色值可以相互进行转换:
col1.toRgb()
col4.toHex()
颜色变换: 覆盖: var colo5 =
col2 .overlayWith(
col3 );
如果col2进行了这个操作,不仅会得到一个新的颜色col5,col2也会被覆盖。 转换: col2.toGrayscale()
转换成灰度图颜色,其他变换可以查api得到。 颜色应用:
//简单使用色值
new fabric.Rect({
left: 100,
top: 100,
width: 100,
height: 100,
fill: col2.toRgb()
})
// 渐变填充 横向填充效果
rect.setGradient('fill',{
x1: 0,
y1: 0,
x2: circle.width, y2: 0,
colorStops:{
0: col1.toRgb(),
1: col3.roRgb()
}
})
动画
对于图形对象的属性,通过 set
进行设置,如果想要将这个属性设置动画效果,类似css中的transition,可以指定属性进行设置。
rect.animate('left', "500", { //设置距离左边的偏移量500
onChange: canvas.renderAll.bind(canvas),
duration: 2000,
easing: fabric.util.ease.easeInOutBounce //动画效果
})
不想计算动画最终的数值,你可以使用 +=``-=
计算符号
rect.animate('left', "+=500", { //设置距离相对当前左边的偏移量加500
onChange: canvas.renderAll.bind(canvas),
duration: 2000,
easing: fabric.util.ease.easeInOutBounce //动画效果
})
animate函数的第三个参数中常用的属性有:
-
from
:允许指定动画属性的起始值(如果我们不希望使用当前值)。 -
duration
:动画持续时间 -
onComplete
:完成时的回调函数 -
onChange
:数值变化时调用的函数 -
easing
:动画变化的曲线
文本
fabric不仅以对象的形式操作文本,还提供了比canvas操作文本 更多的功能 :
支持多行输入、文字对齐方式选择、文字背景设置、文本修饰、文本行高、设置字间距、修改样式、富文本(支持标签)、在 canvas
进行输入编辑。 常用的创建文本的方法有下面两种,它们的参数:第一个参数是文本内容,第二个则是文本的属性对象
var txt = new fabric.Text('aker', {
left: 140, // 位置
top: 140,
shadow: 'rgba(0,0,0,0.3) 15px 15px 15px', // 阴影
fontFamily: 'Hoefler Text', // 字体
stroke: '#ff1318', // 画笔,用于字体边框
strokeWidth: 2, // 画笔粗度
fill: '#0f0', //填充颜色
fontSize: 60, // 字体大小
});
var tex = new fabric.IText('click',{left:100,top:400, minWidth: 50}); //继承自Text,实现设置焦点、可编辑
对于文本的操作属性和css中的属性特别类似,还可以对文本进行背景色等等设置。常用的属性除了上面几个,还有: fontWeight、textDecoration、fontStyle、textAlign、textBackgroundColor、lineHeight
等等
组合
前面讲的都是对单个元素的创建以及操作,fabric也提供了将创建的对象进行组合的方法 group
,将几个对象进行组合成为一个新的对象之后进行操作:
var canvas = new fabric.Canvas('main');
var circle = new fabric.Circle({
radius: 100,
fill: '#eef',
scaleY: 0.5,
originX: 'center',
originY: 'center'
});
var text = new fabric.Text('hello world', {
fontSize: 30,
originX: 'center',
originY: 'center'
});
var group = new fabric.Group([ circle, text ], {
left: 150,
top: 100,
angle: -10
});
canvas.add(group);
效果图
如果在创建对象的时候,没有对每个元素的位置进行设置,组合之后默认是在group的中心点进行放置对象,如果需要设置对象在组合中的位置,可以在创建对象的时候设置位置,如:
var circle3 = new fabric.Circle({
radius: 50,
fill: 'blue',
left: 200
});
group可以看作是一个小型的canvas,因为它和canvas操作对象很类似。在创建完group之后,可以对添加的对象进行操作:
group.item(0).set('fill', 'red');
group.item(1).set({
text: 'trololo',
fill: 'white'
});
常用的操作items方法还有: size()
表示组中所有对象的数量。 contains()
允许检查特定对象是否在组中, add
添加对象, remove
移除对象, addWithUpdate
组的中心添加对象并更新组的属性。
事件
fabric不仅提供了创建了对象的方法,也提供对创建的对象进行事件监听的方法。在fabric官网中也给出了对鼠标移动事件的demo。fabric事件监听类似jq里面对事件的处理。下面是fabric对鼠标点击事件监听demo:
var canvas = new fabric.Canvas('main');
canvas.on('mouse:down', function(options) {
console.log(options.e.clientX, options.e.clientY);
if (options.target) { //加入点在图层对象上面
console.log('an object was clicked! ', options.target.type);
}
});
var rect = new fabric.Rect({
left: 100,
top: 100,
fill: '#f0f',
width: 30,
height: 30
});
canvas.add(rect);
输出结果
fabric提供的事件比较少,不过相对于自己用原生去写肯定方便很多,提供的事件有:
-
鼠标响应事件:”mouse:down”, “mouse:move”,和 “mouse:up”.
-
一般性事件:”after:render”
-
选择事件:”before:selection:cleared”, “selection:created”, “selection:cleared”.
-
对象事件:”object:modified”, “object:selected”, “object:moving”, “object:scaling”, “object:rotating”, “object:added”, and “object:removed”
官方文档上对于object:moving”和”object:scaling有特别备注,这两个事件特别灵敏,哪怕只是1px的变化也会产生响应,所以如果使用这两个事件的话,需要添加防抖。使用好这些事件应该可以满足许多的场景,比如画布的保存,可以对 object:modified
进行监听,如果发生了就存储,那么可以避免修改丢失。 前三种事件都是在画布上面,对于事件对象可以通过options参数获得,后面的对象事件也可以用于图层对象,加入创建了rect对象,监听选中时间:
rect.on('selected', function() {
console.log('selected a rectangle');
});。
我的实验结果是这样的,上面的对象on事件的时候并没有反应(也许是使用问题)。
序列化
对于一个应用程序,如果只是提供在上面进行操作的方法并不够,要不然就会成为一个纯展示用的应用,还需要提供一个能够保存数据或者提取数据的方法。fabric提供了很好的序列化和反序列化方法,可以保存数据为json、base64的图片、svg、对象object、字符串toString。
var canvas = new fabric.Canvas('main');
console.log(canvas.toString())
对于所有的画布对象都有toString方法,我们自己也可以创建对象进行toString覆盖。
对于toString只能得到简单的输出结果,并不能直观获取到对象详细信息,我们可以使用toObject或者toJson(这两个类似):
console.log(rect.toObject())
console.log(rect.toJSON())
console.log(rect.toString())
输出结果如下,展开结果可以看到对于没设置的属性会默认给0或者null。
对于反序列化需要注意的是loadFromJSON对应toJSON、loadFormDatalessJSON对应toDatalessJSON。但是由于性能考虑,不是所有属性都可以进行序列化, fabric
只是包装了一些常用的属性,所以如果设置了一些比较少用的属性,在加载JSON数据的时候需要重新修改图像的属性。更多关于序列化可以查看 文档 。
体验
资料
fabricjs.com/articles/ www.321332211.com/thread?topi…
注:随便写的一些 demo ,有兴趣的玩一下
今天的文章Fabricjs——玩转Canvas分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/21843.html