前言
因为这次接到的需求是要做一个可视化的图片编辑工具,所以经过选型和竟品调研,最终确定用fabric.js来实现,其和要实现的功能匹配度很高,下面简单对fabric.js进行下介绍。
简介
Fabric.js is a framework that makes it easy to work with HTML5 canvas element. It is an interactive object model on top of canvas element. It is also an SVG-to-canvas parser.
Fabric.js是一个可以简化canvas开发的框架。 Fabric.js为canvas提供所缺少的对象模型,同时也是一个svg解析器。
Example
官网给出的例子,功能比较全:demo
特点
非常强大的底层画布能力
用对象的方式去编写代码
可以自定义模块
用法
安装fabric.js,前提要先安装canvas依赖,安装canvas出错的时候可以按照这个装下
npm install fabric —save
安装成功后,先画个简单的正方形
let canvas = new fabric.Canvas('main') // id为main的canvas元素
// 可以在dom中直接设置canvas的宽高,也可以在js里动态改变宽高
canvas.setDimensions({
width: 1000,
height: 600
})
let rect = new fabric.Rect({
left: 100,
top: 100,
fill: 'red',
width: 200,
height: 200,
})
canvas.add(rect) // 把object加到canvas中
一些通用的属性:
position: left, top
dimension: width, height
render: fill, opacity, stroke, strokeWidth
scale & rotate: scaleX, scaleY, angle
flip: flipX, flipY
常用的几种fabric.js class:
- fabric.Rect:矩形
- fabric.Circle:圆形
- fabric.Triangle:三角形
- fabric.Ellipse:椭圆
- fabric.Line:线
- fabric.Polygon:多边形
- fabric.Polyline:折线
下面附上代码:
// 椭圆
let ellipse = new fabric.Ellipse({
left: 320,
top: 100,
originX: 'left', // 横向基准点
originY: 'top', // 垂直基准点
rx: 150, // 横轴
ry: 100, // 竖轴
angle: 0,
fill: '',
stroke: 'red',
strokeWidth: 3,
})
canvas.add(ellipse)
// 线
let line = new fabric.Line([ 260, 125, 260, 375 ], {
fill: 'red',
stroke: 'red',
strokeWidth: 5,
selectable: false
})
canvas.add(line)
// 多边形
// 各个顶点
let points = [
{x: 0, y: 42},
{x: 155, y: 0},
{x: 155, y: 243},
{x: 0, y: 256}
]
let polygon = new fabric.Polygon(points, {
left: 0,
top: 0,
fill: 'purple',
})
canvas.add(polygon)
// 折线
let polylinePoint = []
// fabric提供的random方法
let random = fabric.util.getRandomInt
polylinePoint.push(new fabric.Point(random(100, 200), random(200, 300)))
polylinePoint.push(new fabric.Point(random(200, 300), random(100, 200)))
polylinePoint.push(new fabric.Point(random(200, 250), random(150, 200)))
let polyline = new fabric.Polyline(polylinePoint, {
stroke: 'black',
fill: ''
})
canvas.add(polyline)
let circle = new fabric.Circle({
radius: 20,
fill: 'green',
left: 100,
top: 100
})
let triangle = new fabric.Triangle({
width: 20,
height: 30,
fill: 'blue',
left: 50,
top: 50
})
canvas.add(circle, triangle)
运行结果:
还有path,不过感觉用到的比较少
// M代表MoveTo,L代表LineTo,Z代表closePath
let path = new fabric.Path('M 0 0 L 50 0 M 0 0 L 4 -3 M 0 0 L 4 3 Z', {
left: 380,
top: 70,
stroke: 'red',
strokeWidth: 2,
fill: false
})
canvas.add(path)
运行结果:
文本
分为普通文本(Text)和可编辑的文本(IText)
let iText = new fabric.IText('hello\nworld', {
left: 50,
top: 50,
fontFamily: 'Helvetica',
fill: '#333',
lineHeight: 1.1,
// 可以单独设置每个字符的style
styles: {
0: {
0: { fontSize: 80 },
1: { textBackgroundColor: 'red' }
},
1: {
0: { textBackgroundColor: 'rgba(0,255,0,0.5)' },
4: { fontSize: 20 }
}
}
})
canvas.add(iText)
运行结果:
说完了基础的创建对象的方法,下面说一些其他特性
动画
// 第一个参数是要改变的属性,第二个参数是改变的值,支持在原来的基础上做改变,第三个参数是回调函数
rect.animate('left', '+=500', {
onChange: canvas.renderAll.bind(canvas),
duration: 2000, // 动画持续时间
easing: fabric.util.ease.easeOutBounce // fabric提供了很多种动画方式
})
渐变色
circle.setGradient('fill', {
// 色标的位置
x1: 0,
y1: 0,
x2: circle.width,
y2: circle.height,
// 渐变的颜色
colorStops: {
0: 'red',
0.2: 'orange',
0.4: 'yellow',
0.6: 'green',
0.8: 'blue',
1: 'purple'
}
})
结果:
group
// 也可以嵌套组
let group = new fabric.Group([circle, triangle], {
left: 150,
top: 100,
angle: 10
})
canvas.add(group)
结果:
下面说下图片的加载
let imgElement = document.querySelector('.img') // dom中的img元素
let imgInstance = new fabric.Image(imgElement, {
left: 200,
top: 100,
angle: -10,
opacity: 0.85
})
canvas.add(imgInstance)
实际应用中很少会这样写,因为还需要在dom中写img标签,一般来说都是引用url来加载图片
fabric.Image.fromURL('url', image => {
image.set({
left: 200,
top: 100,
width: 200,
height: 200 // 这里的宽高会是裁剪图片,不是缩放,是fabric object的宽高
})
// .scale(1.2, 1.2) // 缩放图片x、y轴
.scaleToWidth(200) // 按需要缩放到固定的宽或高
.setCoords()
canvas.add(image)
}, { crossOrigin: 'anonymous' })
fabric还支持给图片加滤镜
fabric.Image.fromURL('url', img => {
img.set({
left: 500,
top: 100,
})
// 支持多个滤镜效果叠加
img.filters.push(
new fabric.Image.filters.Noise({noise: 200}), // 噪声滤镜
new fabric.Image.filters.Invert(), // 反转
new fabric.Image.filters.Sepia(), // 深褐色
new fabric.Image.filters.Brownie() // 棕镜
)
// 加载滤镜到图片上
img.applyFilters()
canvas.add(img)
}, { crossOrigin: 'anonymous' })
fabric提供了好多种滤镜,可以自己根据需求选用,还支持矩阵来自定义滤镜(Convolute)
加载SVG,其实和加载图片差不多
fabric.loadSVGFromURL('test.svg', (objects, options) => {
let loadedObject = fabric.util.groupSVGElements(objects, options)
loadedObject.set({
left: 500,
top: 200
})
.setCoords()
canvas.add(loadedObject)
// loadedObject.sourcePath = 'test.svg'
// let json = canvas.toJSON(['test'])
// let lessJson = canvas.toDatalessJSON(['test'])
// console.log(json)
// console.log(lessJson)
})
在这里顺便说下toJSON方法,就是把整个canvas都转换成JSON对象,以便需要的时候使用,可以直接用loadFromJSON载入。
上面还写了一个toDatalessJSON,这个一般用在svg比较多的时候,因为svg载入之后是以object-path来保存的,所以大的svg会有很多的path,toJSON之后会过长,所以toDatalessJSON可以把path用路径来代替,不过需要手动设置下sourcePath,以便下次使用的时候能找到。
fabric.js也提供了很多事件以供使用:
一些配置
canvas.preserveObjectStacking = true // 选中的时候是否显示在最上层
canvas.selection = false // 是否支持多选
// 选中框的一些设置
fabric.Object.prototype.set({
transparentCorners: false,
borderColor: 'rgba(32,160,255,1)',
cornerColor: 'rgba(32,160,255,1)',
cornerStrokeColor: 'rgba(32,160,255,1)',
padding: 0,
cornerSize: 5,
rotatingPointOffset: 20,
})
配置项太多了,需要的自己看下API吧
小结
fabric.js用起来还是很简单的,不过也比较底层,实际应用起来还是需要自己封装很多东西。
基础用法就写这些了,进阶用法等有时间再写一写。
ps. 官方文档和API看的是真头疼。。。