工作需要,开始学习fabricjs
一、在vuejs环境下,先跑起来
安装
按照官方的说法,如果要在vue.js中跑fabric.js,需要依赖一个node-cavas的库,去年还需要手动安装,而且由于牵涉到node-gpy, gtk2等第三方库,去年折腾了很久也不行,不过今天安装挺顺利。
//创建项目库
vue create hello-fabric
//安装fabric.js
npm install fabric --save
直接就把fabric.js v4.5以及相关的依赖都安装成功了,还挺顺利的
跑第一个例子
直接跑github官网的例子就可以:
在新创建的vue项目的Home.vue文件内添加,代码如下
<template>
<div class="home">
<button @click="onDraw">绘制</button>
<canvas id="canvas" width="800" height="400"></canvas>
</div>
</template>
<script>
// @ is an alias to /src
import HelloWorld from "@/components/HelloWorld.vue";
import { fabric } from "fabric";
export default {
name: "Home",
components: {
HelloWorld,
},
methods: {
onDraw() {
this.initCanvas();
},
initCanvas() {
var canvas = new fabric.Canvas("canvas", { backgroundColor: 'rgb(100,100,200)'});
var rect = new fabric.Rect({
top: 100,
left: 100,
width: 60,
height: 70,
fill: "red",
});
canvas.add(rect);
},
},
};
</script>
点击按钮之后,运行结果如下图所示,丑是丑了点,算是跑起来了。
二、为什么要用fabricjs
简单一句话,因为canvas的api太low了,没有对比就没有伤害。
同样一个功能,在画布上绘制一个红色矩形
用canvas写是这样的
// reference canvas element (with id="c")
var canvasEl = document.getElementById('c');
// get 2d context to draw on (the "bitmap" mentioned earlier)
var ctx = canvasEl.getContext('2d');
// set fill color of context
ctx.fillStyle = 'red';
// create rectangle at a 100,100 point, with 20x20 dimensions
ctx.fillRect(100, 100, 20, 20);
用fabricjs写是这样
// create a wrapper around native canvas element (with id="c")
var canvas = new fabric.Canvas('c');
// create a rectangle object
var rect = new fabric.Rect({
left: 100,
top: 100,
fill: 'red',
width: 20,
height: 20
});
// "add" rectangle onto canvas
canvas.add(rect);
现在看起来还差不多,但是如果我们要把这个矩形顺时针旋转45度呢
canvas是这样
var canvasEl = document.getElementById('c');
var ctx = canvasEl.getContext('2d');
ctx.fillStyle = 'red';
ctx.translate(100, 100);
ctx.rotate(Math.PI / 180 * 45);
ctx.fillRect(-10, -10, 20, 20);
fabricjs是这样
var canvas = new fabric.Canvas('c');
// create a rectangle with angle=45
var rect = new fabric.Rect({
left: 100,
top: 100,
fill: 'red',
width: 20,
height: 20,
angle: 45
});
canvas.add(rect);
这就开始展现fabric的优势了
如果更进一步,在绘制好矩形之后,我们想要把他挪一下位置,
canvas的做法
var canvasEl = document.getElementById('c');
...
ctx.strokRect(100, 100, 20, 20);
...
// erase entire canvas area
ctx.clearRect(0, 0, canvasEl.width, canvasEl.height);
ctx.fillRect(20, 50, 20, 20);
fabricjs的做法
var canvas = new fabric.Canvas('c');
...
canvas.add(rect);
...
rect.set({ left: 20, top: 50 });
canvas.renderAll();
一切的根源,主要是canvas中没有图形对象的概念,他能够操控的只有画布本身,所以他来来回回的都只能在画布上想办法。
而fabricjs就不同了,他引入了图形对象的概念,一切的操作都是对对象来的,这种API的设计对开发人员就友好多了。
三、fabricJS对象
1、基础对象
fabricjs定义了以下7大基础对象,实际上还应该加上fabric.Image, fabirc.Text两个对象,总共是9大核心基础对象。
-
fabric.Circle
-
fabric.Ellipse
-
fabric.Line
-
fabric.Polygon
-
fabric.Polyline
-
fabric.Rect
-
fabric.Triangle
2、对象操作
fabricJS为对象提供了一些列的属性,可以通过修改对象的属性来改变对象的展现
常见的属性有, left, top, with, height, fill, opacity, stroke, strokeWidth(边框), scaleX, scaleY, angle, flipX, flipY(翻转, true, false), skewX, skewY(倾斜, angle, 0-90),这里要注意,skew和angle是不一样的,angle只是旋转,不改变形状,而skew是将整个object按照角度倾斜拉升,会改变他的形状。
四、Canvas
fabric.Canvas对象其实是fabric.Object的对象管理器,通过他,你可以:
-
添加、删除对象
-
配置画布的一些属性,比如背景色
-
是否是可交互的;
关于canvas的交互性,Canvas的对象编辑功能默认是打开的,如果想关闭,有两种方式:
-
方式1,canvas.selection = false
-
方式2,使用fabric.StaticCanvas取代fabric.Canvas
这个fabric.StaticCanvas相当于是一个轻量版的fabric.Canvas,其实他只是没有事件响应,其他都一样。
在某些场景下,如果我们不需要事件响应,同时想要整个软件包小一点,此时就可以用StaticCanvas,并且编译的时候取消部分模块。
五、图像 Image
显示图片的方式有好几种,一种我最不喜欢的是这样,先添加到html中,再添加到canvas中,有点傻
html
<canvas id="c"></canvas>
<img src="my_image.png" id="my-image">
js
var canvas = new fabric.Canvas('c');
var imgElement = document.getElementById('my-image');
var imgInstance = new fabric.Image(imgElement, {
left: 100,
top: 100,
angle: 30,
opacity: 0.85
});
canvas.add(imgInstance);
相对来说,下面这种我更喜欢一些,也更实用,你只要有图片路径就可以了
fabric.Image.fromURL('my_image.png', function(oImg) {
canvas.add(oImg);
});
但是这种方式我感觉也有点问题,因为他是通过回调来添加到画布中的,那就意味着添加的时间点无法控制,这样可能导致在反序列化之后,图片在画布内的各个对象的顺序发生变化,这点以后可能会遇到。
六、Path 路径
前面我们学习了如何绘制常规的对象以及图片,接下来我们来看看更强大的:Path和Groups,这样两个可以帮我们绘制复杂对象。
我们一般不会自己手动去创建Path对象,而是使用fabric内置的 svg path对象,这点以后再来学习,下面我们看看Path是怎么回事。
var canvas = new fabric.Canvas('c');
var path = new fabric.Path('M 0 0 L 200 100 L 170 200 z');
path.set({ left: 120, top: 120 });
canvas.add(path);
上面的这些Path指令M 0 0 L 200 100 L 170 200 z啥意思呢?其实也好理解,M表示Move,L表示Line,Z表示结束了。
绘制了这么个图形
下面来看看一个稍微复杂一点的图形,就这么个箭头,用Path来绘制是这样的。
...
var path = new fabric.Path('M121.32,0L44.58,0C36.67,0,29.5,3.22,24.31,8.41\
c-5.19,5.19-8.41,12.37-8.41,20.28c0,15.82,12.87,28.69,28.69,28.69c0,0,4.4,\
0,7.48,0C36.66,72.78,8.4,101.04,8.4,101.04C2.98,106.45,0,113.66,0,121.32\
c0,7.66,2.98,14.87,8.4,20.29l0,0c5.42,5.42,12.62,8.4,20.28,8.4c7.66,0,14.87\
-2.98,20.29-8.4c0,0,28.26-28.25,43.66-43.66c0,3.08,0,7.48,0,7.48c0,15.82,\
12.87,28.69,28.69,28.69c7.66,0,14.87-2.99,20.29-8.4c5.42-5.42,8.4-12.62,8.4\
-20.28l0-76.74c0-7.66-2.98-14.87-8.4-20.29C136.19,2.98,128.98,0,121.32,0z');
canvas.add(path.set({ left: 100, top: 200 }));
上面的C指令表示贝塞尔曲线,
是不是有点吓人,这也是为什么上面说我们一般不会手动去绘制Path,而是会从一些事先编辑好的svg文件中加载,使用fabric.loadSVGFromString
or fabric.loadSVGFromURL
这样的方法来加载,所以以后我做编辑器的时候,也需要内置写图形给客户用,有了Path,我能做的事情就多了。
好了,这部分就讲到这里,下一篇我们会介绍成组、动画、文本、SVG解析、显示、序列化、事件、图像滤镜等功能。