一、基于canvas画布的实用类Fabric.js的使用Part.1
Fabric.js简介
开始
方法
事件
canvas常用属性
对象属性
图层层级操作
复制和粘贴
二、基于canvas画布的实用类Fabric.js的使用Part.2
锁定
拖拽和缩放画布
分组
动画
图像滤镜
渐变
右键菜单删除
三、基于canvas画布的实用类Fabric.js的使用Part.3
自由绘画
绘制背景图片
绘制文本
绘制线和路径
自由绘制矩形
自由绘制圆形
自由绘制椭圆形
自由绘制三角形
自由绘制多边形
Fabric对象可以添加一些属性进行锁定,例如静止水平移动、静止垂直移动,静止缩放等等
let rect = new fabric.Rect({
width: 100,
height: 50,
fill: '#ffde7d',
top: 20,
left: 20
})
rect.lockMovementX = true
canvas.add(rect)
let rect = new fabric.Rect({
width: 100,
height: 50,
fill: '#ffde7d',
top: 20,
left: 20
})
rect.lockMovementY = true
let rect = new fabric.Rect({
width: 100,
height: 50,
fill: '#ff9a3c',
top: 60,
left: 160
})
rect.lockRotation = true
let rect = new fabric.Rect({
width: 100,
height: 50,
fill: '#ffde7d',
top: 20,
left: 20
})
rect.lockScalingX = true
let rect = new fabric.Rect({
width: 100,
height: 50,
fill: '#f95959',
top: 20,
left: 20
})
rect.lockScalingY = true
let boundingBox = new fabric.Rect({
top: 100,
left: 100,
width: 600,
height: 400,
fill: '#f95959',
selectable: false
})
let movingBox = new fabric.Rect({
top: 150,
left: 150,
width: 100,
height: 100,
fill: 'yellow',
hasBorders: false,
hasControls: false,
hoverCursor: 'move'
})
this.canvas.add(boundingBox);
this.canvas.add(movingBox);
this.canvas.on("object:moving", (opt) => {
let top = movingBox.top;
let left = movingBox.left;
let topBound = boundingBox.top;
let bottomBound = topBound + boundingBox.height;
let leftBound = boundingBox.left;
let rightBound = leftBound + boundingBox.width;
opt.target.left = Math.min(Math.max(left, leftBound), rightBound - movingBox.width)
opt.target.top = Math.min(Math.max(top, topBound), bottomBound - movingBox.height)
})
Groups是Fabric最强大的功能之一,它可以将任意数量的Fabric对象组合在一起,形成一个小组,分组后,所有对象都可以一起移动、修改、缩放、旋转甚至更改其外观等
let group = new fabric.Group([circle, text], {
left: 100,
top: 100,
angle: -10
})
canvas.add(group)
修改分组的某个对象的属性:
group.item(0).set("fill","red");
group.item(1).set({
text:"trololo",
fill:"white"
})
分组时要记住的另一件事是对象的状态。例如,在与图像组成组时,需要确保这些图像已完全加载:
fabric.Image.fromURL(logo, img => {
let img1 = img.scale(0.3).set({left: 0, top: 0})
fabric.Image.fromURL(logo, img => {
let img2 = img.scale(0.3).set({left: 80, top: 0})
fabric.Image.fromURL(logo, img => {
let img3 = img.scale(0.3).set({left: 160, top: 0})
let group = new fabric.Group([img1, img2, img3], {
left: 10,
top: 400
})
canvas.add(group)
})
})
})
每个Fabric对象都有一个animate方法,该方法可以动画化该对象,animate(动画属性,动画的结束值,[动画的详细信息])
let rect = new fabric.Rect({
left: 100,
top: 100,
width: 100,
height: 100,
fill: 'red'
})
rect.animate("angle", 45, {
onChange: canvas.renderAll.bind(canvas)
})
canvas.add(rect)
第一个参数是要设置动画的属性。第二个参数是动画的结束值。如果矩形具有-15°的角度,并且我们传递了45,则动画将从-15°变为45°。第三个参数是一个可选对象,用于指定动画的详细信息-持续时间,回调,缓动等
rect.animate("angle", 45, {
from: 0, // 允许指定可设置动画的属性的起始值(如果我们不希望使用当前值)
duration: 1000, // 默认为500(ms),可用于更改动画的持续时间
easing: fabric.util.ease.easeOutBounce, // 缓动功能 easeOutBounce、easeInCubic、easeOutCubic、easeInElastic、easeOutElastic、easeInBounce、easeOutExpo
onChange: canvas.renderAll.bind(canvas), // 在每次刷新时都会执行
onComplete: (e) => { console.log(e) } // 在动画结束时调用的回调
})
animate的一个方便之处在于它还支持相对值
// 向右移动100px
rect.animate('left', '+=100', {
onChange: canvas.renderAll.bind(canvas)
})
// 逆时针旋转5度
rect.animate('angle', '-=5', {
onChange: canvas.renderAll.bind(canvas)
})
fabric.Image的每个实例都具有“ filters”属性,该属性是一个简单的过滤器数组。该阵列中的每个过滤器都是Fabric过滤器之一的实例。或您自己的自定义过滤器的实例。
let url = 'http://localhost:82/public/img/5.png' // 图片url
let base64Url = await this.imgUrlToBase64(url) // 图片base64 url
// 正常照片
fabric.Image.fromURL(url, img => {
img.scale(0.3)
canvas.add(img)
})
// 单个滤镜
fabric.Image.fromURL(base64Url, img => {
img.scale(0.3)
img.left = 300
// 添加滤镜
img.filters.push(new fabric.Image.filters.Grayscale())
// 图片加载完成之后,应用滤镜效果
img.applyFilters()
canvas.add(img)
})
// 叠加滤镜
fabric.Image.fromURL(base64Url, img => {
img.scale(0.3)
img.set({
left: 300,
top: 250,
})
img.filters.push(
new fabric.Image.filters.Grayscale(),
new fabric.Image.filters.Sepia(), //色偏
new fabric.Image.filters.Brightness({ brightness: 0.2 }) //亮度
)
img.applyFilters()
canvas.add(img)
})
(说明:这里图片可能会出错,放本地图片地址会报“Cannot read property 'naturalWidth' of null”的错误,直接放网络图片地址会报“Failed to execute 'texImage2D' on 'WebGLRenderingContext': The image element contains cross-origin data, and may not be loaded.”的错误。解决方法就是将转为Base64格式)
Fabric支持在所有对象上设置填充或描边属性的渐变,首先创建渐变,然后将其分配给填充或描边。
// 圆
let circle = new fabric.Circle({
left: 100,
top: 100,
radius: 50,
})
let gradient = new fabric.Gradient({
type: 'linear', // linear or radial
gradientUnits: 'pixels', // pixels or pencentage 像素 或者 百分比
coords: { x1: 0, y1: 0, x2: circle1.width, y2: 0 }, // 至少2个坐标对(x1,y1和x2,y2)将定义渐变在对象上的扩展方式
colorStops:[ // 定义渐变颜色的数组
{ offset: 0, color: 'red' },
{ offset: 0.2, color: 'orange' },
{ offset: 0.4, color: 'yellow' },
{ offset: 0.6, color: 'green' },
{ offset: 0.8, color: 'blue' },
{ offset: 1, color: 'purple' },
]
})
circle.set('fill', gradient);
canvas.add(circle)
let circle = new fabric.Circle({
left: 100,
top: 100,
radius: 50
})
let gradient = new fabric.Gradient({
type: 'radial',
coords: {
r1: 50,
r2: 0,
x1: 50,
y1: 50,
x2: 50,
y2: 50,
},
colorStops: [
{ offset: 0, color: '#fee140' },
{ offset: 1, color: '#fa709a' }
]
})
circle.set('fill', gradient);
canvas.add(circle)
this.canvas.on('mouse:wheel', this.onMouseWheel)
// 监听鼠标放大缩小事件
onMouseWheel(opt) {
let delta = opt.e.deltaY // 滚轮,向上滚一下是 -100,向下滚一下是 100
let zoom = this.canvas.getZoom() // 获取画布当前缩放值
zoom *= 0.999 ** delta
zoom = zoom > 10 ? 10 : (zoom < 0.1 ? 0.1 : zoom) // 最大放大10倍,最小缩小至10%
this.canvas.zoomToPoint({ // 以鼠标指针位置为基准缩放
x: opt.e.offsetX,
y: opt.e.offsetY
}, zoom)
opt.e.preventDefault()
opt.e.stopPropagation()
}
删除