javascriptFabric.js轻而易举操作canvas的神奇库个人文章

今天我要向你们介绍Fabric.js—一个能够让你轻而易举操作canvas的神奇的库.Fabric不仅提供了一个虚拟canvas对象,还有svg渲染器,交互层,还有一整套十分有用的工具.这是一个完全开源的项目,MIT协议,多年以来依靠许多贡献者共同维护.

Fabric开始与2010,在经历过原生canvas繁琐的API操作之后.原作者就写了一个可交互的编辑器printio.ru—允许用户自定义外观.那时候只有flashapp需要这种交互.光阴似箭,经过一点点积累形成了现在的Fabric.

让我们进一步看一看!

为什么选择fabric现在的Canvas支持我们去创造一些充满创造力神奇的图形但是它提供的api实在是水平低到令人发指.如果我们只是想画一些简单的图形.但是却需要一系列操作,各种修改中心点,如果要画一个复杂图形—那操作就“更有意思了”.

Fabric的目标就是解决这些问题.

原生canvas方法只允许我们使用一些简单的图形操作,然后在画布上瞎子摸象.想画一个矩形使用fillRect(left,top,width,height).想画一条线用moveTo(left,top)和lineTo(x,y)组合.这感觉就像用画笔在画布上画画,随着画的越来越多,画布内容的可控性就越差.

为了避免这种低水平操作,Fabric在基础上提供了一个简单且强大的对象模型.更注重于画布的状态和渲染,现在,让我们开始学习使用“对象”吧.

让我们通过一个简单的例子画一个红色的矩形来看看两者有什么不同.这是原生API的实现

//获取画布的引用varcanvasEl=document.getElementById('c');//获取2dcontext对象用来操作(之前提到的bitmap)varctx=canvasEl.getContext('2d');//给当前上下文设置颜色ctx.fillStyle='red';//在100,100的位置创建一个20*20的矩形ctx.fillRect(100,100,20,20);现在,让我们看看fabricjs怎么实现同样的效果://包裹一下canvas(withid="c")varcanvas=newfabric.Canvas('c');//新建一个矩形对象varrect=newfabric.Rect({left:100,top:100,fill:'red',width:20,height:20});//将矩形添加到canvas里canvas.add(rect);目前为止,最不同的地方在尺寸的设置—两个例子很像.但是你应该也意识到两种操作思想的不同了吧.用原生方法,我们操作context上下文—代表着整个canvas.用Fabric,我们在具体对象上操作—实例化它们,修改他们的属性,然后给它们添加到canvase上.这些对象是fabricjs世界的第一公民.

但是画一个红色的矩形没啥难度.我们来整点有意思的!比如,稍微的旋转一下

我们试试旋转45度.首先,使用原生方法:

varcanvasEl=document.getElementById('c');varctx=canvasEl.getContext('2d');ctx.fillStyle='red';ctx.translate(100,100);ctx.rotate(Math.PI/180*45);ctx.fillRect(-10,-10,20,20);接下来使用fabric:varcanvas=newfabric.Canvas('c');//createarectanglewithangle=45varrect=newfabric.Rect({left:100,top:100,fill:'red',width:20,height:20,angle:45});canvas.add(rect);

发生了什么

我们只需要修改对象的's“angle”为45.使用原生方法,事情变得越来越“有趣了”.我们不能操作对象.反而为了实现需求,我们给整个canvasbitmap旋转了(ctx.translate,ctx.rotate).然后在画矩形上去,别忘了原点定位为(-10,-10),这样才能看起来是在(100,100).

现在我确信你已经清楚了fabricjs存在的意义,还有他帮助我门减少了多少低级代码.

让我们再看另一个例子—追踪canvas状态.

假设在某一个点,我们想要移动刚才的矩形到canvas上的另一个点如果不能操作对象,我们会怎么做是不是只能再调一遍fillRect

不仅如此.在调用另一个fillRect时候,我们在画布上画了一个新的矩形,但是现在已经有一个了.记得我之前提到的擦出功能吗为了“移动”,我们必须先擦除之前的画布,然后在新的位置画新的矩形.

varcanvasEl=document.getElementById('c');...ctx.strokRect(100,100,20,20);...//清除整个画布ctx.clearRect(0,0,canvasEl.width,canvasEl.height);ctx.fillRect(20,50,20,20);用fabric怎么实现varcanvas=newfabric.Canvas('c');...canvas.add(rect);...rect.set({left:20,top:50});canvas.renderAll();注意最重要的区别.用过Fabricjs,我们不用再为了实现“移动”清除上一个画布.只需要操作对象,简单的修改它们的属性,然后re-rendercanvas获取“最新的画面”.

对象现在我们已经了解了怎么操作fabric.Rect构造函数生成实例.当然Fabric默认包含了许多基础形状—原,三角,椭圆,等等.这些都挂载在fabric“变量下”像fabric.Circle,fabric.Triangle,fabric.Ellipse,等等.

Fabric提供的7中基础图形:

fabric.Circle圆fabric.Ellipse椭圆fabric.Line线段fabric.Polygon多边形fabric.Polyline折线fabric.Rect矩形fabric.Triangle三角形想要画一个圆只需要创建圆对象,然后添加到canvas中.和其他基础图形一样:

varcircle=newfabric.Circle({radius:20,fill:'green',left:100,top:100});vartriangle=newfabric.Triangle({width:20,height:30,fill:'blue',left:50,top:50});canvas.add(circle,triangle);

..现在我们在100,100有了一个绿色的原型,50,50有了一个蓝色的三角形.

操纵对象创建几何图形—矩形,圆,或者其他—仅仅是开始.以后,我们可能需要修改这些对象.也许是某些动作触发的改变,或播放某种动画.或者想要在鼠标事件时修改对象某些属性(颜色,透明度,尺寸,位置).

Fabric替我们关心了渲染和状态维护的事情.我们只需要在对象上做手脚就行.

之前的例子展示了set方法并且调用set({left:20,top:50})从之前的位置“移动”走了.类似的方式,我们可以修改任何属性.但是有啥属性呢

是的,在fabric中创建翻转对象只需要给flip*属性设置为true.

你可通过getmethod读取所有属性,然后使用set方法.让我们试试修改红色矩形的属性:

varcanvas=newfabric.Canvas('c');...canvas.add(rect);rect.set('fill','red');rect.set({strokeWidth:5,stroke:'rgba(100,200,200,0.5)'});rect.set('angle',15).set('flipY',true);

首先,我们设置“fill”为“red”,将图像变成红色的了.下一行设置了“画笔宽度”和“画笔颜色”的值,给矩形一个5px宽的浅绿色边框.最后,我们修改“angle”和“flipY”属性.注意三行不同的设置语法,都支持.

这个例子展示了set方法的通用性.你以后会经常用到它,所以这个方法尽量的支持各种使用方法.

讲完了设置属性,那么如果获取呢只需要使用通用的get方法,当然还有各种特殊的get*,来获取一个属性.想要获取一个对象的“width”,可以用get('width')或者getWidth().想要获取“scaleX”属性—get('scaleX')或者getScaleX(),等等.对象“公共”属性都有getWidth或getScaleX这种方法(“stroke”,“strokeWidth”,“angle”,等.)

你可能注意到了,在之前的例子里写初始化配置生成的对象和使用set方法创建的没什么区别.这是因为他们就是完全一样.你可以在初始化的时候使用“配置”,或者在创建对象之后再使用set方法:

varrect=newfabric.Rect({width:10,height:20,fill:'#f55',opacity:0.7});//一样的varrect=newfabric.Rect();rect.set({width:10,height:20,fill:'#f55',opacity:0.7});默认配置到这里,你可能想问—不传“配置”创建对象发生了什么.还有那些属性吗

当然有.Fabricjs中的对象一直会有默认属性的.如果在创建的时候省略,就是使用默认值.试试看:

varrect=newfabric.Rect();//没有配置传入

rect.get('width');//0rect.get('height');//0

rect.get('left');//0rect.get('top');//0

rect.get('fill');//rgb(0,0,0)rect.get('stroke');//null

rect.get('opacity');//1这个矩形都使用了默认值.定位在0,0,黑色,完全不透明,没有边框没有尺寸(宽高都是0).因为都是0,所以我们看不见.只要给宽高附上正整数后,我们就能看在一个黑色矩形在画布左上角.

HierarchyandInheritanceFabric对象并不是独立存在的.他们都继承自一个源对象

大多数对象都继承自根对象fabric.Object.fabric.Object代表着一个二维,有着坐标和宽高,以及一系列其他图形特征.这些就是之前看到的对象属性—fill,stroke,angle,opacity,flip*,等.

使用继承,可以让我们在fabric.Object上定义方法,然后提供给所有子类.比如,你想给所有对象都加一个自定义getAngleInRadians方法,你可以直接在fabric.Object.prototype上定义

fabric.Object.prototype.getAngleInRadians=function(){returnthis.get('angle')/180*Math.PI;};varrect=newfabric.Rect({angle:45});rect.getAngleInRadians();//0.785...varcircle=newfabric.Circle({angle:30,radius:10});circle.getAngleInRadians();//0.523...circleinstanceoffabric.Circle;//truecircleinstanceoffabric.Object;//true正如你所见,这个方法立刻在所有实例上都生效了.

当创建子“类”的时候,子类上经常要定义一些属于自己的属性和方法.例如,fabric.Circle需要“radius”属性.fabric.Image—在下面会讲到—需要getElement/setElement方法用于访问/设置HTML元素.在高级项目中使用原型来获取自定义渲染和行为非常常见.

Canvas现在已经详细的说完了Fabricjs对象,让我门回过头来说一下canvas.

在所有的Fabricjs例子中,你看到的第一行是不是创建canvas对象?—newfabric.Canvas('...').fabric.Canvas包裹着元素,它负责着所有Fabric.Object对象.传入一个id,返回fabric.Canvas实例.

我们可以将对象add进去,通过引用关系,也可以删除他们:

varcanvas=newfabric.Canvas('c');varrect=newfabric.Rect();canvas.add(rect);//添加进去canvas.item(0);//获取刚才添加的fabric.Rectcanvas.getObjects();//获取画布中所有的对象canvas.remove(rect);//删除fabric.Rect所以fabric.Canvas的主要作用就是管理对象,它还可以写一些配置.想要给画布设置背景对所有内容进行裁剪设置不同的宽/高是否可交互包括但不限于这些属性可以传给fabric.Canvas,同对象一样,在任何时候都可以:

对象模型的存在允许以编程方式访问和操作画布上的对象.但是对于用户来说,需要用鼠标或者手指操作.当你通过newfabric.Canvas('...')初始化画布之后,可以选择拖动旋转缩放等,甚至是群选之后一起操作!

如果我们想让用在在画布上拖拽一些东西—比如一张图片—我们只需要创建画布,加一个图片进去.不需要任何额外的操作.

我们可以使用把布尔值传给Fabric's“selection”或者对象的穿一个布尔值给对象的“selectable”字段来控制是否可交互.

varcanvas=newfabric.Canvas('c');...canvas.selection=false;//关闭群选rect.set('selectable',false);//单个对象不可选如果不想要这个交互功能你可以使用fabric.StaticCanvas代替fabric.Canvas.别的都一样.

varstaticCanvas=newfabric.StaticCanvas('c');staticCanvas.add(newfabric.Rect({width:10,height:20,left:100,top:100,fill:'yellow',angle:30}));这样创建了一个“轻量”版本的canvas,没有任何事件处理逻辑.你还是可以操作全部的对象模型—添加对象,删除或修改他们,或者修改canvas配置—这些都还是一如既往能用.只是事件系统没了.

总之,如果你需要一个不需要交互的画布,就要择更轻量的StaticCanvas就够了.

图片说到图片…

在画布上玩矩形圆形没什么意思,我们来试试玩图片正如你认为的,Fabric也让这个变得简单.让我们实例化一个fabric.Image对象然后把它添加进canvas:

(html)

(js)

varcanvas=newfabric.Canvas('c');varimgElement=document.getElementById('my-image');varimgInstance=newfabric.Image(imgElement,{left:100,top:100,angle:30,opacity:0.85});canvas.add(imgInstance);注意,我们将一个图片元素纯给了fabric.Image构造函数.这样就创建了fabric.Image的实例.并且,我们立刻设置了图片的坐标、旋转、透明度.加入到画布中后,会看见一个图片在100,100的位置,旋转了30度,还有轻微的透明度.不错吧

那么,如果文档中没有这个图片元素怎么办,我们只是有一个url那么就到了fabric.Image.fromURL派上用场的时候了

fabric.Image.fromURL('my_image.png',function(oImg){canvas.add(oImg);});看起来是不是非常简单直观只是调用fabric.Image.fromURL,传了url,在图片加载完成之后调用一下回调函数.回调函数的第一个默认传参就是fabric.Image对象.在这时候,你就可以像之前一样操作修改属性了,然后加入到画布中:

fabric.Image.fromURL('my_image.png',function(oImg){//scaleimagedown,andflipit,beforeaddingitontocanvasoImg.scale(0.5).set('flipX',true);canvas.add(oImg);});路径我们先了解了简单的图形,然后是图片.下面看看更复杂的图形和内容

首先看一对强力组合—路径和分组.

在Fabric中,路径代表着一个可以背修改,填充,描边的形状.路径是由一堆命令组成的,本质上是在模仿一支笔从一个点到另一个点.通过“move”,“line”,“curve”,或者“arc”命令,可以组成神奇的图案.借助路径的分组功能Paths(PathGroup's),让用户发挥想象的空间就更大了.

Fabric中的Paths与SVGelements很像.使用相同的语法,所以可以互相转化.稍后我们将更仔细地研究序列化和SVG解析,先提醒你一下,你后几乎不会手动创建Path实例.而你会经常使用Fabric's内置的SVG渲染器.但是为了理解Path,我们先尝试手动创建一个简单的:

varcanvas=newfabric.Canvas('c');varpath=newfabric.Path('M00L200100L170200z');path.set({left:120,top:120});canvas.add(path);

我们实例化了一个fabric.Path对象,给它传了一串字符串路径指令.虽然看起来神秘,但是它其实很容易理解.“M”代表“move”命令,命令那只不可见的笔指在0,0的位置.“L”代表着“line”用笔画到200,100的位置.然后,另一个“L”画了一条170,200的线.最后,“z”命令画笔闭合这条线段,确定最终形状.这样我们就得到了一个三角形.

显而易见fabric.Path只是Fabric中的另一种对象,我们同样可以修改他的属性.但是我们可以改的更多:

...varpath=newfabric.Path('M00L300100L200300z');...path.set({fill:'red',stroke:'green',opacity:0.5});canvas.add(path);出于好奇,让我们试一试稍微复杂一点的图形.你会发现我之前说的对,没有办法手写路径.

...varpath=newfabric.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}));“M”还是代表着“move”,所以画笔从“121.32,0”开始.然后“L”代表这画一条直线搭到“44.58,0”.目前位置还能接受.“C”命令,代表着“三次贝塞尔曲线”.命令画笔从当前位置到“36.67,0”画一条三次贝塞尔曲线.开始控制点为“29.5,3.22”,结束控制点为“24.31,8.41”.然后再跟上一堆的贝塞尔曲线,最终形成了这个好看的箭头.

通常来说,你不会直接这么“粗暴”的使用,你可能会用到fabric.loadSVGFromString或fabric.loadSVGFromURL这类方法来加载SVG文件,把这些工作全部交给Fabric.

说到整个SVG文档,Fabric的path代表着SVG元素,SVG文档中经常出现的路径集合,在Fabric中就是组的概念(fabric.Group实例).正如你想到的,组不过是一组路径和其他对象的集合.并且fabric.Group继承自fabric.Object,所以它的添加、修改行为和其他对象一样.

就像使用路径一样,您可能不会直接使用它们.但是一旦你需要,你应该知道它的原理.

后记我们只是介绍了Fabric一些基础的东西.你现在可以轻松的在canvas上操作简单的复杂的图形,图片了。—位置,尺寸,旋转,颜色,边框,透明度.

该系列的下一章,我们会讲组;动画;文班;SVG解析,渲染,序列化;事件;图片滤镜等等.

与此同时,去看看示例或者基础数据或者别的地方,或者直接看文档,wiki,和源代码.

THE END
1.使用FabricJS对大图像应用滤镜(巨坑)farbic.js缩放图片背景:我司在canvas的渲染模板的宽高都大于2048px 都几乎接近4000px,就导致使用FabricJS的滤镜功能图片显示异常 新知识:滤镜是对图片纹理的处理 FabricJS所能支持的最大图片纹理是2048的 一但图片超出2048的纹理尺寸 当应用滤镜时,图像会被剪切或者是缩放。 https://blog.csdn.net/2303_77072102/article/details/144405056
2.[新需求]:裁剪工具功能增强,支持get和set写法·Issue#IB9KJB新需求提供了什么功能? 裁剪工具功能增强,支持get和set写法 该需求带来的价值、应用场景? Thanks for submitting the issue. For more commands, please visitfor help. If you need to change the subscription of a Pull Request or Issue, please visit thelink.https://gitee.com/openharmony/interface_sdk-js/issues/IB9KJB
3.图形编辑器基于Paper.js教程17:图像转gcode前的处理,灰度,黑白js的函数实现 代码语言:javascript 复制 /** * 将图像的每个像素转换为灰度 * @param {HTMLImageElement} image - 要转换的图像 * @param {HTMLCanvasElement} canvas - 目标 canvas 元素 */functionconvertImageToGrayscale(image,canvas){constctx=canvas.getContext('2d');// 将图像绘制到 canvas 上canvas.https://cloud.tencent.com/developer/article/2476927
4.javaPhantomJs截图速度快吗mob64ca140f29e5的技术博客JS截图上传图片 在前端WEB开放过程中,经常使用上传图片、上传视频、上传音频以及上传其他文件等,通常都使用到各种上传插件,但是很多插件只是单纯的上传文件,不具备图片截图,即使有也很传统,今天我自己写了通过鼠标在图片进行绘制需要截图的矩形框便可以进行截图,很方便,很快捷,可以应用各种场景,比如轮播图只需要某个部分https://blog.51cto.com/u_16213679/12810827
5.ChatGPT画布模式超棒,这4种用法必知代码应用程序canvassectioChatGPT 的新画布模式为世界领先的生成式人工智能工具中的写作与编辑增添了新的维度。 文本编辑 要是您想编辑文本,ChatGPT 画布相当出色。 您能够用滑块依照您的受众来调整阅读水平。比如说,您或许希望让博客文章对普通大众更好理解,而研究论文则要有行业术语。 https://www.163.com/dy/article/JJBMR7QF05568E4N.html
6.如何使用FabricJS裁剪克隆图像中的顶部偏移?js教程 // Initiate a canvas instance var canvas = new fabric.Canvas("canvas"); canvas.setWidth(document.body.scrollWidth); canvas.setHeight(250); // Initiating the image element var imageElement = document.getElementById("img1"); // Initiate a shadow object var shadowhttps://www.php.cn/faq/606241.html
7.Fabric.js动态裁剪单个对象前端开发问题本文介绍了Fabric.js 动态裁剪单个对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧! 问题描述 我正在动态添加一个矩形元素来裁剪/剪辑(使用clipTo)选定的元素,它在第一次时效果很好,但是当我在画布上添加第二个元素并开始裁剪第二个元素时,第一个元素会丢失裁剪/https://www.genban.org/ask/web/46796.html
8.fabricjs图像自定义裁剪形状fabricjs 图像加载-等比缩放图像到画布这篇文章描述了如何进行图像等比缩放,但是加载的图片形状仅限于矩形或者正方形,如果需要显示其他形状,那就需要另寻他法, 效果 image.png 代码实现 // 初始化设置画布大小varcanvas=newfabric.Canvas("canvas",{width:800,height:600,});// 椭圆fabric.Image.fromURL('../puhttps://www.jianshu.com/p/569c7d849f00
9.如何使用FabricJS在多边形上添加一个剪裁区域要在多边形上添加剪裁区域,您需要使用FabricJS中的Masking功能。以下是一些步骤,可以帮助您将剪裁区域应用于多边形: 创建多边形:使用FabricJS的fabric.Polygon来创建多边形对象。 创建剪裁区域:使用fabric.Path对象创建剪裁路径,例如圆形或矩形。 将剪裁区域应用于多边形:使用clipTo属性将多边形对象的裁剪区域设置为剪裁路径对https://www.volcengine.com/theme/3346423-R-7-1
10.[开源]基于fabric.js的多页面图片设计,支持导入PDFPSDSVG基于fabric.js的多页面图片设计,使用 Vue3 + TypeScript + Fabric.js + Element-Plus,支持 文字、图片、形状、线条、二维码 、条形码几种最常用的元素类型,每一种元素都拥有高度可编辑能力,缩略图显示,模板,支持导出json,svg, image文件。 二、开源协议 https://code.exmay.com/detail/21809
11.canvas2d开发框架是做什么的?互联网3. Fabric.js Fabric.js是一个基于Canvas 2D的开发框架,它提供了一套易自制漫画app于使用的API,可以方便地创建、管理和操作图形元素和动画效果。Fabric.js的原理是使用Canvas API绘制图形,并使用requestAnimationFrame方法在每帧之间进行重绘。Fabric.js还提供了一个Canvas对象,可以方便地管理和操作Canvas元素。Fabric.https://www.yimenapp.net/knowledge/hulianwang-15390.html
12.fabricfabric.js 是一个基于 HTML5 canvas 的图片编辑库,提供了丰富的功能和灵活的接口,可以用于创建各种图形编辑器和图片处理工具。fabric.js 支持对图像进行缩放、旋转、裁剪、变换等操作,同时也支持添加文本、图形、滤镜效果等功能。通过 fabric.js,开发者可以轻松实现图片编辑器的各种需求,例如在线海报设计、头像编辑、https://www.coder100.com/index/index/content/id/3517810
13.Fabric.js从入门到本文主要讲解Fabric.js基础,包括: 画布的基本操作 基础图形绘制方法(矩形、圆形、三角形、椭圆、多边形、线段等) 图片和滤镜的使用 文本和文本框 动画 分组和打散分组 基础事件 自由绘画 裁剪 序列化和反序列化 …… 除此之外,还会讲一些进阶一点的操作,比如: https://xie.infoq.cn/article/8234f81029edab7cb70c1348a
14.CesiumJSPrimitiveAPI高级着色入门明确一个定义,在Primitive API中应用着色器,实际上是给Appearance的vertexShaderSource、fragmentShaderSource或Material中的fabric.source设置着色器代码,它们所能控制的层级不太一样。但是他们的共同目的都是为了 Geometry 服务的,它们会随着 CesiumJS 的每帧 update 过程,创建 ShaderProgram,创建 DrawCommand,最终去到 Webhttps://www.mvrlink.com/cesiumjs-primitiveapi-advanced-coloring-beginner-using-glsl-shaders/