一,前言

1.fabric [ˈfæbrɪk'] 是一个功能强大的运行在HTML5 canvasJavaScriptfabriccanvas提供了一个交互式对象模型,通过简洁的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元素时可直接设置widthheight ,当一开始不确定宽高时可不设置,之后使用setWidthsetHeight动态设置

canvasCtx.setWidth(400)
canvasCtx.setHeight(400)

4.相应的可以使用getWidthgetHeight获取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)widthheight

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)和长短半轴rxry

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中,我们使用对象的topleft来定位对象在画布中的位置,且topleft默认是对象的左上角位置

2.我们可以通过配置对象的originXoriginY来修改默认原点的位置

3.originXoriginY分别代表对象平移的水平起始点和垂直起始点,可以设置的值如下

originX : "left"|"right"|"center"
originY : "top"|"bottom"|"center"

4.如下图所示,相同的lefttop值,原点不一样时,对象的位置是不一样的,红色的为默认的原点,紫色的originXoriginYcenter


5.除了lefttop, 我们可以通过对象的aCoords获取对象在没缩放没移动时的原始位置,

七,kclass对象

1.往深层面看,绘制的每一个图形都是一个kclass对象,如下

2.对于所有的对象,需要使用add 方法添加进画布

3.我们可以使用getObjects获取所有绘制的对象,返回一个元素为kclass对象的数组,注意没有add进画布的对象,无法通过getObjects获取到

canvasCtx.getObjects()

3.在kclass可以获取对象的一些有用的信息其中

(1)lineCoords : 线性对象边界的四个点坐标,是在画布缩放移动时,动态变化的当前时刻快照的对象坐标

(2)aCoords : 原始对象边界的四个点坐标原始值,该属性反映了画布没缩放没移动时的对象位置,

每一个lineCoords都对应着一个aCoordslineCoords是当前肉眼看到的,aCoords是隐藏在背后的原始位置。

(3)top,left :对象定位时的topleft

(4)angle:对象旋转的角度

(5)自定义的一些属性,也会在kclass对象中展示

(6)配置的属性等等

八,设置对象属性

1.对于所有对象,除了在创建时可以声明属性,我们还可以使用对象的set实例方法动态设置属性

 directionArrow.set({left: 10,top: 22,});

九,限制激活对象的操作行为

1.正常情况下一个可交互的画布上的元素支持缩放,平移和旋转的操作

2.我们可以通过设置 hasControlsfalse禁用所以功能,此时不会渲染操作框

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实例方法用于绑定事件,当设置对象的属性 eventedfalse时,绑定的事件不生效

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.注意,当对画布进行拖动和缩放后,事件对象的offsetXoffsetY会产生偏移,不能准确的表示位置,需要使用如下的方法转化坐标

//根据缩放等级转化鼠标的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.可以通过topleftwidthheight参数将指定部分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.关键的两个apigetImageDataputImageData

  //初始化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学习相关推荐

  1. 学习整理fabric.js更换画布文字元素字体样式

    学习整理fabric.js更换画布文字元素字体样式 原图 效果图 实现代码 index.html script.js 生成本地图 原图 效果图 实现代码 index.html <!DOCTYPE ...

  2. 学习整理Fabric.js 实现文本文字加粗、下划线、斜体、竖排、字体对齐代码

    原图 效果图 代码 index.html <!DOCTYPE HTML> <html> <head><meta charset="utf-8&quo ...

  3. Fabric.js 图形标注

    需求分析 画布中显示需要标注的图片,鼠标绘制矩形进行标注(矩形绘制在图片需要标注的位置,矩形中显示标注的内容文字).最后可以拿到标注的内容位置信息.标注信息等并且回显所有标注内容. 效果展示 使用的技 ...

  4. 使用fabric.js简简单单实现一个画板

    什么是fabric fabric是一个功能强大的JavaScript库,运行在HTML5 canvas上.fabric为canvas提供了一个交互式对象模型,以及一个svg-to-canvas解析器. ...

  5. 【实战篇】使用fabric.js 快速开发一个图片编辑器

    大厂技术  高级前端  Node进阶 点击上方 程序员成长指北,关注公众号 回复1,加入高级Node交流群 本文由作者@愚坤(秦少卫)投稿授权分享,项目源码已开源,感兴趣的可以点击源码地址学习下 最近 ...

  6. ArcGIS JS 学习笔记4 实现地图联动

    原文:ArcGIS JS 学习笔记4 实现地图联动 1.开篇 守望屁股实在太好玩了,所以最近有点懒,这次就先写个简单的来凑一下数.这次我的模仿目标是天地图的地图联动. 天地的地图联动不仅地图有联动,而 ...

  7. backbone.js学习笔记

    backbone.js学习笔记 之前只接触过jQuery,看来Backbone是除了jQuery的第二大JS框架... backbone到底是个啥? 其实刚开始我也不知道=_=,我是这周二才听说居然还 ...

  8. Canvas实用库Fabric.js使用手册

    简介 什么是Fabric.js? Fabric.js是一个可以简化Canvas程序编写的库. Fabric.js为Canvas提供所缺少的对象模型, svg parser, 交互和一整套其他不可或缺的 ...

  9. 程序员的高速学习法——以JS学习为例,进行图解

    近期一直在忙着学习,感觉做总结的时间太少了,听起来挺好玩儿的,就像<倾城之恋>里面.范柳原说:那时候都忙着谈恋爱了哪里有时间恋爱.  学习和总结也是一样.不能一直忙着学习而导致自己没有时间 ...

最新文章

  1. 按键的使用(一)------verilog
  2. 用Apache Hadoop和Apache Solr处理和索引医学图像
  3. MySQL数据库恢复(LOAD DATA)
  4. 中国为何难学欧盟反垄断
  5. 深度学习基础1(神经网络)
  6. 如何在验证集加噪声_如何使用Python构建机器学习模型
  7. UI设计超干货素材!小图标里的大学问!
  8. 无法启动QPCore Service
  9. python画图代码乔治-2020阅读书单
  10. 电子信息产业发展研究院副主任杨春立:基于数字孪生的智慧城市顶层设计探索与实践...
  11. Matplotlib库学习笔记(4) pyplot的文本显示以及Latex的使用
  12. 创可贴温度计,0排放温室气体:提前领略冬奥会的科技看点
  13. 微信头像挂件来了,想在头像加什么就来加什么吧!
  14. maya! board_3D角色模型很难做?Maya、Zbrush人头建模终极秘笈
  15. wire tox_Tox-rs的漫长旅程。 第1部分
  16. 云计算都有哪些特点?展望云计算的发展前景
  17. 不忘初心,方得始终——NOIP2016前的感悟
  18. 如何让一幅图片逐渐变淡
  19. 手写喜马拉雅APP特效
  20. 2021/03/27 K8S集群日志与监控

热门文章

  1. 计算机二级考试干货内容,干货分享,如何备考计算机二级?
  2. mt4 谐波_谐波原理看美元指数:短期看涨鲨鱼或令多头重获优势!
  3. python datetime时间差_高考倒计时,聊聊Python的GUI
  4. LINGO编程(基础)
  5. 顺序表与链表结构及解析
  6. Python函数设计与使用
  7. python输出古诗词_python爬虫——爬取古诗名句
  8. 如何在flash中实现播放控制?
  9. [UE4教程] UE4蓝图总结(入门)
  10. 纵观网络安全攻击的各种方式方法