fabric.js学习
一,前言
1.fabric
[ˈfæbrɪk']
是一个功能强大的运行在HTML5 canvas
的JavaScript
,fabric
为canvas
提供了一个交互式对象模型,通过简洁的api
就可以在画布上进行丰富的操作。
2.可以使用包管理工具直接安装:npm install fabric
3.fabric
兼容pc
端和移动端
二,初始化画布
1.首先创建一个canvas
元素,作为容器
<canvas id="mapCanvas" width="350" height="200"></canvas>
2.实例化一个canvas
上下文对象,接管原生容器,根据使用api
的不同,初始化后的画布可以分为 可交互 和 不可交互 两种
import { fabric } from "fabric";
//可交互画布,用于需要编辑图片等场景
const canvasCtx = new fabric.Canvas("mapCanvas", {enableRetinaScaling: true,perPixelTargetFind: true, // 对象基于像素检测skipTargetFind: true,//框选selection: true, //是否支持鼠标框选selectable: true, //是否支持鼠标框选selectionColor: "rgba(255,255,255,0.3)", // 鼠标框选背景色selectionLineWidth: 1, // 画布中鼠标框选边框preserveObjectStacking: true, //取消被选中的元素会处于顶层的默认行为backgroundColor: '#fff', //画布背景颜色});//不可交互画布, 用于画海报等场景,鼠标事件都无效
const canvasCtx = new fabric.StaticCanvas("mapCanvas",{})
3.创建canvas
元素时可直接设置width
和height
,当一开始不确定宽高时可不设置,之后使用setWidth
,setHeight
动态设置
canvasCtx.setWidth(400)
canvasCtx.setHeight(400)
4.相应的可以使用getWidth
和getHeight
获取canvas
的宽高
canvasCtx.getWidth()
canvasCtx.getHeight()
三,基础图像绘制
1.fabric
已经内置了许多基础图像,调用相应api
,可直接应用,免去了原生繁琐的过程。
(1)矩形 [ 圆角矩形 ]
(2)圆
(3)椭圆
(4)直线
(5)曲线
(6)折线
(7)虚线
(8)多边形
(9)三角形
2.矩形绘制 fabric.Rect
(1)使用fabric.Rect
绘制矩形,主要配置项为左上角的(left,top)
和width
,height
let forbiddenArea = new fabric.Rect({//主要配置属性left: 0, //距离画布左侧的距离,单位是像素top: 0, //距离画布上边的距离width: 100,height: 100,//样式配置属性fill: "#fef0f08a", //填充的颜色stroke: "#fab6b6", //边界的颜色//通过配置rx,ry,可以让矩形具有圆角rx:20,ry:20,});
2.绘制圆 fabric.Circle
(1)使用fabric.Circle
绘制圆,主要配置项为中心点(left,top)
和半径radius
let circle = new fabric.Circle({//主要配置属性left: 10, //距离左边的距离top: 10, //距离上边的距离radius: 2, //圆的半径//样式配置属性fill: "#eee", //填充的颜色stroke: "#fab6b6", //边界的颜色
});
3.绘制椭圆 fabric.Ellipse
(1)使用fabric.Ellipse
绘制圆,主要配置项为中心点(left,top)
和长短半轴rx
,ry
let circle = new fabric.Ellipse({//主要配置属性left: 10, //距离左边的距离top: 10, //距离上边的距离rx: 10, ry: 10, //样式配置属性fill: "#eee", //填充的颜色
});
4.绘制直线 fabric.Line
(1)使用fabric.Line
绘制直线,主要配置项为两个点x1,y1,x2,y2
let line = new fabric.Line([x1,y1,x2,y2],{stroke: "#c45656",strokeWidth: 3,
});
5.绘制线段 fabric.Polyline
(1)使用fabric.Polyline
绘制线段,主要配置项为多个点x1,y1,x2,y2
const polyline = new fabric.Polyline([{x: 30, y: 30},{x: 150, y: 140},{x: 240, y: 150},{x: 100, y: 30}], {fill: 'transparent', // 如果画折线,需要填充透明stroke: '#6639a6', // 线段颜色strokeWidth: 5 // 线段粗细 })
6.绘制不规则图形 fabric.Path
(1)使用fabric.Path
绘制不规则图形,主要配置项为一个字符串,其中M
代表移动到某个点,L
是中途的点,z
表示闭合
const path = new fabric.Path('M 0 0 L 200 100 L 170 200 z');path.set({ left: 120, top: 120,fill:'red' });
7.绘制曲线
(1)fabric
提供了自由画笔的功能让我们可以随意绘制线条
(2)使用isDrawingMode
来开启自由绘制模式
//1.在初始化canvas实例时,直接开启自由画笔const canvasCtx = new fabric.Canvas("mapCanvas", {isDrawingMode:true,});//2.设置`isDrawingMode`动态开启canvasCtx.isDrawingMode =true;//设置画笔颜色 canvasCtx.freeDrawingBrush.color = "#f56c6c";//设置画笔粗细canvasCtx.freeDrawingBrush.width = 3;
(3)关闭自由绘制
//设置isDrawingMode为falsecanvasCtx.isDrawingMode =false;//关闭的时机可以根据需求设置,这里介绍鼠标弹起时关闭canvasCtx.on("mouse:up", function (opt) {this.isDrawingMode = false;});
(4)自由绘制的曲线,也会生成实例对象
8.绘制虚线
(1)绘制虚线要使用strokeDashArray
属性,strokeDashArray[a,b]
含义为 每隔a
个像素空b
个像素,直线和线段都可以使用这个属性来绘制成虚线。
const line = new fabric.Line([x1,y1,x2,y2],{stroke: "#c45656",strokeWidth: 3,strokeDashArray: [20, 10],
});const polyline = new fabric.Polyline([{ x: 30, y: 30 },{ x: 150, y: 140 },{ x: 240, y: 150 },{ x: 100, y: 30 },],{fill: "transparent", // 如果画折线,需要填充透明hasBorder: true,strokeDashArray: [20, 10],});
四,图片绘制
1.将图片绘制进canvas
有两种方式
(1)方式一:根据图片元素绘制图片,使用fabric.Image
let image = new Image();image.src = 'xxxx';image.onload = ()=>{//1.创建图片实例对象let imgInstance = new fabric.Image(image, {left: 0, //位置top: 0,scaleX:1,scaleY:1,erasable:false, //是否可擦除hasControls: false, // 是否开启图层的控件evented:true,//是否可以支持事件...});//实例对象的width和height可以获取图片的大小imgInstance.widthimgInstance.height//2.添加到画布canvasCtx.add(imgInstance);};
(2)方式二:根据图片地址绘制图片fabric.Image.fromURL
new fabric.Image.fromURL("/resources/images/robot.png", function (oImg) {//oImg是图片对象实例oImg.set({top:10,left:10,scaleX:1,scaleY:1,evented: false,...});//实例对象的width和height可以获取图片的大小oImg.widthoImg.heightcanvasCtx.add(oImg);});
2.当我们已经声明了一个fabric
图片对象,可以在维持原对象的情况下使用setSrc
动态修改图片。
//注意,第一个参数只能是图片地址远程地址本地地址,base64等,不能是图像元素oimg.setSrc("./img.png", () => {canvasCtx.renderAll();});
五,绘制文本
1.绘制普通文本
let text = new fabric.Text(`hello \n world!`, {left: 0,top: 0,fill: 'red', // 字体颜色fontSize: 12, //字体大小fontWeight: 100, //字体粗细charSpacing: 10 //字体间距,angle: 30, // 旋转backgroundColor: '#ffd460', // 背景色stroke: '#3f72af', // 文字描边颜色(蓝色)strokeWidth: 2, // 文字描边粗细textAlign: 'lfet', // 对齐方式:left 左对齐; right 右对齐; center 居中opacity: 0.8, // 不透明度selectable: true, // 能否被选中,默认trueshadow: 'rgba(0, 0, 0, 0.5) 5px 5px 5px', // 投影...});
2.绘制可编辑文本
let text = new fabric.IText(`hello \n world!`, {left: 0,top: 0,cornerColor: 'pink', // 角的颜色(被选中时)borderColor: 'yellowGreen', // 边框颜色(被选中时)...});
3.绘制文本框
let text = new fabric.Textbox(`hello \n world!`, {left: 0,top: 0,cornerColor: 'pink', // 角的颜色(被选中时)borderColor: 'yellowGreen', // 边框颜色(被选中时)...});
4.可以通过set
实例方法动态修改文本,和其他属性
text.set({text:'change content'
})
六,对象的定位
1.在fabric
中,我们使用对象的top
和left
来定位对象在画布中的位置,且top
和left
默认是对象的左上角位置
2.我们可以通过配置对象的originX
和originY
来修改默认原点的位置
3.originX
和originY
分别代表对象平移的水平起始点和垂直起始点,可以设置的值如下
originX : "left"|"right"|"center"
originY : "top"|"bottom"|"center"
4.如下图所示,相同的left
和top
值,原点不一样时,对象的位置是不一样的,红色的为默认的原点,紫色的originX
和originY
为center
5.除了left
和top
, 我们可以通过对象的aCoords
获取对象在没缩放没移动时的原始位置,
七,kclass
对象
1.往深层面看,绘制的每一个图形都是一个kclass
对象,如下
2.对于所有的对象,需要使用add
方法添加进画布
3.我们可以使用getObjects
获取所有绘制的对象,返回一个元素为kclass
对象的数组,注意没有add
进画布的对象,无法通过getObjects
获取到
canvasCtx.getObjects()
3.在kclass
可以获取对象的一些有用的信息其中
(1)lineCoords
: 线性对象边界的四个点坐标,是在画布缩放移动时,动态变化的当前时刻快照的对象坐标
(2)aCoords
: 原始对象边界的四个点坐标原始值,该属性反映了画布没缩放没移动时的对象位置,
每一个lineCoords
都对应着一个aCoords
,lineCoords
是当前肉眼看到的,aCoords
是隐藏在背后的原始位置。
(3)top
,left
:对象定位时的top
和left
(4)angle
:对象旋转的角度
(5)自定义的一些属性,也会在kclass
对象中展示
(6)配置的属性等等
八,设置对象属性
1.对于所有对象,除了在创建时可以声明属性,我们还可以使用对象的set
实例方法动态设置属性
directionArrow.set({left: 10,top: 22,});
九,限制激活对象的操作行为
1.正常情况下一个可交互的画布上的元素支持缩放,平移和旋转的操作
2.我们可以通过设置 hasControls
为false
禁用所以功能,此时不会渲染操作框
3.同时我们也可以通过属性配置,限制一部分行为。
(1)限制元素的旋转:object.lockRotation = true
(2)限制元素x
轴的缩放:object.lockScalingX= true
(3)限制元素y
轴的缩放:object.lockScalingY= true
(4)限制元素上下移动:object.lockMovementY =true
(5)限制元素左右移动:object.lockMovementX =true
4.另一种方式使用对象的实例方法setControlsVisibility
,该方法用于隐藏操作框的部分corner
,从而达到禁用功能
workNode.setControlsVisibility({bl: false,br: false,mb: false,ml: false,mr: false,mt: false,tl: false,tr: false,mtr:false,});
5.对于删除按钮,需要自定义
var deleteImg = document.createElement("img");
deleteImg.src = deleteIcon;fabric.Object.prototype.controls.deleteControl = new fabric.Control({x: 0.5,y: -0.5,offsetY: -16,offsetX: 16,cursorStyle: "pointer",mouseUpHandler: function (eventData, transform) {var target = transform.target;//target 为当前对象,这里可执行业务判断canvasCtx.remove(target);canvasCtx.requestRenderAll();},render: function (ctx, left, top, styleOverride, fabricObject) {//fabricObject为当前对象,可根据当前对象自定义是否渲染删除按钮var size = this.cornerSize + 2;ctx.save();ctx.translate(left, top);ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle));//deleteImg 是图片元素ctx.drawImage(deleteImg, -size / 2, -size / 2, size, size);ctx.restore();},cornerSize: 18,
});
九,事件
1.画布对象和元素对象都有on
实例方法用于绑定事件,当设置对象的属性 evented
为false
时,绑定的事件不生效
canvasCtx.on(eventname,handler)canvasCtx.on("mouse:down",(e)=>{})
text.on("mouse:down",(e)=>{})
2.支持的常用事件
(1)鼠标上常用的操作事件
mouse:down 或 mousedown 鼠标按下时触发
mouse:move
mouse:up 或 mouseup 鼠标抬起时触发
mouse:down:before
mouse:move:before
mouse:up:before
mouse:over 或 mouseover 鼠标悬浮时触发
mouse:out 或 mouseout 鼠标进入后离开时触发
mouse:dbclick 或 mousedblclick 鼠标双击时触发//for example
canvasCtx.on("mouse:down",(e)=>{})
text.on("mouse:down",(e)=>{})
(2)对象操作的一些监控
modified
rotating
scaling
moving
skewing//for example
text.on("rotating",(e)=>{})
3.fabric
的鼠标事件能够兼容在移动端的手势操作
mouse:down ==> 在移动端手指点击一下也会触发
mouse:move ==> 在移动端手指移动也会触发
mouse:up ==> 在移动端手指抬起也会触发mouse:down:before
mouse:move:before
mouse:up:beforemouse:over ==> 不支持移动端
mouse:out ==> 移动端手指离开元素触发
mouse:dbclick ==> 在移动端双击也会触发
4.注意,虽然部分鼠标事件兼容移动端,但是同一个事件在PC
端和移动端返回的事件对象是不一样的,pc
端返回的mouseEvent
,移动端返回的touchEvent
,两者返回的字段含义不一样,要自己做兼容。
5.注意,当对画布进行拖动和缩放后,事件对象的offsetX
,offsetY
会产生偏移,不能准确的表示位置,需要使用如下的方法转化坐标
//根据缩放等级转化鼠标的x,y
function getTransformedPosX(canvasCtx, x) {let zoom = Number(canvasCtx.getZoom());return (x - canvasCtx.viewportTransform[4]) / zoom;
}
function getTransformedPosY(canvasCtx, y) {let zoom = Number(canvasCtx.getZoom());return (y - canvasCtx.viewportTransform[5]) / zoom;
}
十,橡皮擦
1.fabric.js
的基础包并没有包含橡皮擦模块,要使用橡皮擦功能可以使用npm
安装fabric-with-erasing
。
2.fabric-with-erasing
是在fabric.js
的基础上加上橡皮擦,因此在使用fabric-with-erasing
后,可以不需要fabric
包。
3.开启橡皮擦
canvasCtx.isDrawingMode = true; // 进入绘画模式canvasCtx.freeDrawingBrush = new fabric.EraserBrush(canvasCtx); // 使用橡皮擦画笔canvasCtx.freeDrawingBrush.width = 8; // 设置画笔粗细为 10
4.恢复橡皮擦擦除部分
canvasCtx.isDrawingMode = true;canvasCtx.freeDrawingBrush = new fabric.EraserBrush(canvasCtx);canvasCtx.freeDrawingBrush.width = 10;canvasCtx.freeDrawingBrush.inverted = true;
5.关闭橡皮擦功能
canvasCtx.isDrawingMode = false;
6.橡皮擦经过的部分会变成透明的
十,设置画布zoom
和获取zoom
1.canvas
默认层级是1
2.设置层级方法: canvasCtx.setZoom(zoom);
3.获取层级方法: canvasCtx.getZoom();
4.根据鼠标滚轮来设置层级:
canvasCtx.on("mouse:wheel", function (opt) {var delta = opt.e.deltaY;var zoom = canvasCtx.getZoom();zoom *= 0.999 ** delta;if (zoom > 20) zoom = 20;if (zoom < 0.01) zoom = 0.01;canvasCtx.setZoom(zoom);opt.e.preventDefault();opt.e.stopPropagation();});
十一,修改鼠标样式
1.fabric
支持修改不同状态下默认的鼠标样式
(1)默认的鼠标样式
canvasCtx.defaultCursor = 'default'
(2)鼠标移动到对象上的样式
canvasCtx.hoverCursor = 'move'
(3)鼠标拖动时的样式
canvasCtx.moveCursor = 'move'
(4)自由绘制时的样式
canvasCtx.freeDrawingCursor = 'crosshair'
(5)旋转时的样式
canvasCtx.rotationCursor = 'crosshair'
2.上面的样式都是默认样式,我们可以赋值为其它css
支持的cursor
值
十二,将画布保存为图片
1.使用toDataURL
可以将canvas
转为图片,该函数返回的是图片的base64
格式字符串。
let imgUrl = canvasCtx.toDataURL({format: "png",})
2.可以通过top
,left
, width
和height
参数将指定部分canvas
绘制成图片。
let imgUrl = canvasCtx.toDataURL({format: "png",width: mapImgInstance.lineCoords.br.x - mapImgInstance.lineCoords.bl.x,height: mapImgInstance.lineCoords.bl.y - mapImgInstance.lineCoords.tr.y,left: mapImgInstance.lineCoords.bl.x,top: mapImgInstance.lineCoords.tl.y,});
十三,释放canvas
1.使用dispose
可以释放已经创建的canvas
canvasCtx.dispose()
十四,移动端手势支持
1.使用fabric_with_gestures
版本
??做个假想,使用这个版本纯天然支持双指缩放
/* 要想触发 必须是fabric-with-gesturestouch:gesturetouch:dragtouch:shaketouch:longpress
2.双指缩放
handleDoubleFinger(options) {const {clientX: finger1X,clientY: finger1Y} = options.e.targetTouches[0];const {clientX: finger2X,clientY: finger2Y} = options.e.targetTouches[1];const powX = (finger2X - finger1X) * (finger2X - finger1X);const powY = (finger2Y - finger1Y) * (finger2Y - finger1Y);// 计算两个手指之间的距离const distance = Math.sqrt(powX + powY);// 每次缩放的比例let ratio = -0.05;if (distance > preDistance) {ratio = 0.05;}preDistance = distance;const x = scaleCenter.x || (Math.abs(finger1X + finger2X)) / 2;const y = scaleCenter.y || (Math.abs(finger1Y + finger2Y)) / 2;scaleCenter = {x, y};// 计算当前缩放的大小let zoom = ratio + canvasCtx.getZoom(); // 获取当前缩放比zoom = Math.max(0.5, zoom);zoom = Math.min(3, zoom);const zoomPoint = new fabric.Point(x, y);canvasCtx.zoomToPoint(zoomPoint, zoom);}
十五,操作像素
1.fabric
好像没有直接操作像素的方法,想要操作像素可以使用原生的canvas
2.关键的两个api
是getImageData
和putImageData
//初始化canvas上下文let canvas = document.getElementById("canvas");let ctx = canvas.getContext("2d");//初始化图像元素let img = new Image();img.crossOrigin = "anonymous";img.src = url; // url是要改变图像的地址//图像加载完成后img.onload = () => {canvas.width = img.width;canvas.height = img.height;//往canvas绘制图像元素ctx.drawImage(img, 0, 0);//获取图像像素对象let imgData = ctx.getImageData(0, 0, img.width, img.height);//imgData.data 类似于 [r1,g1,b1,a1,r2,g2,b2,a2,r3,g3,b3,a3,...] 每四个元素组成一个rgba//...根据索引可以直接修改像素值//使用putImageData可以把改变后的图片,重新绘制到canvas上ctx.putImageData(imgData, 0, 0);//之后可以将图片重新下载下来let url = canvas.toDataURL("image/png", { quality: 1 });}
十六,参考资料
1.中文api文档
fabric.js学习相关推荐
- 学习整理fabric.js更换画布文字元素字体样式
学习整理fabric.js更换画布文字元素字体样式 原图 效果图 实现代码 index.html script.js 生成本地图 原图 效果图 实现代码 index.html <!DOCTYPE ...
- 学习整理Fabric.js 实现文本文字加粗、下划线、斜体、竖排、字体对齐代码
原图 效果图 代码 index.html <!DOCTYPE HTML> <html> <head><meta charset="utf-8&quo ...
- Fabric.js 图形标注
需求分析 画布中显示需要标注的图片,鼠标绘制矩形进行标注(矩形绘制在图片需要标注的位置,矩形中显示标注的内容文字).最后可以拿到标注的内容位置信息.标注信息等并且回显所有标注内容. 效果展示 使用的技 ...
- 使用fabric.js简简单单实现一个画板
什么是fabric fabric是一个功能强大的JavaScript库,运行在HTML5 canvas上.fabric为canvas提供了一个交互式对象模型,以及一个svg-to-canvas解析器. ...
- 【实战篇】使用fabric.js 快速开发一个图片编辑器
大厂技术 高级前端 Node进阶 点击上方 程序员成长指北,关注公众号 回复1,加入高级Node交流群 本文由作者@愚坤(秦少卫)投稿授权分享,项目源码已开源,感兴趣的可以点击源码地址学习下 最近 ...
- ArcGIS JS 学习笔记4 实现地图联动
原文:ArcGIS JS 学习笔记4 实现地图联动 1.开篇 守望屁股实在太好玩了,所以最近有点懒,这次就先写个简单的来凑一下数.这次我的模仿目标是天地图的地图联动. 天地的地图联动不仅地图有联动,而 ...
- backbone.js学习笔记
backbone.js学习笔记 之前只接触过jQuery,看来Backbone是除了jQuery的第二大JS框架... backbone到底是个啥? 其实刚开始我也不知道=_=,我是这周二才听说居然还 ...
- Canvas实用库Fabric.js使用手册
简介 什么是Fabric.js? Fabric.js是一个可以简化Canvas程序编写的库. Fabric.js为Canvas提供所缺少的对象模型, svg parser, 交互和一整套其他不可或缺的 ...
- 程序员的高速学习法——以JS学习为例,进行图解
近期一直在忙着学习,感觉做总结的时间太少了,听起来挺好玩儿的,就像<倾城之恋>里面.范柳原说:那时候都忙着谈恋爱了哪里有时间恋爱. 学习和总结也是一样.不能一直忙着学习而导致自己没有时间 ...
最新文章
- 按键的使用(一)------verilog
- 用Apache Hadoop和Apache Solr处理和索引医学图像
- MySQL数据库恢复(LOAD DATA)
- 中国为何难学欧盟反垄断
- 深度学习基础1(神经网络)
- 如何在验证集加噪声_如何使用Python构建机器学习模型
- UI设计超干货素材!小图标里的大学问!
- 无法启动QPCore Service
- python画图代码乔治-2020阅读书单
- 电子信息产业发展研究院副主任杨春立:基于数字孪生的智慧城市顶层设计探索与实践...
- Matplotlib库学习笔记(4) pyplot的文本显示以及Latex的使用
- 创可贴温度计,0排放温室气体:提前领略冬奥会的科技看点
- 微信头像挂件来了,想在头像加什么就来加什么吧!
- maya! board_3D角色模型很难做?Maya、Zbrush人头建模终极秘笈
- wire tox_Tox-rs的漫长旅程。 第1部分
- 云计算都有哪些特点?展望云计算的发展前景
- 不忘初心,方得始终——NOIP2016前的感悟
- 如何让一幅图片逐渐变淡
- 手写喜马拉雅APP特效
- 2021/03/27 K8S集群日志与监控