强大的Canvas开源库Fabric.js简介与开发指南
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
什么是Fabric.js?Fabric.js 是一个强大且简单的Javascript HTML5 Canvas库。 官网地址:http://fabricjs.com/ 为什么要使用Fabric.js?Canvas提供一个好的画布能力, 但是Api不够友好。绘制简单图形其实还可以, 不过做一些复杂的图形绘制, 编写一些复杂的效果,就不是那么方便了。Fabric.js就是为此而开发,它主要用对象的方式去编写代码。 Fabric.js能做的事情
它提供了灵活丰富的Api和可配置化参数轻松实现复杂的效果,该开源库已被许多开发者用于项目实践中,广受好评。 下载趋势图 项目开发实战这里基于React框架为基础,介绍Fabric.js开发实战实例。 1、安装Fabric.jsnpm install fabric --save 或 yarn add fabric 官网还支持按需模块定制构建,在你需要的特性模块前面勾选,然后一键构建。这样可以使得你整体的代码量减少。2、引入Fabric.jsimport {fabric} from 'fabric'; 3、initCanvas 画布初始化//创建画布 let canvasObj = new fabric.Canvas('snackCanvas'); //设置画布背景色 canvasObj.setBackgroundColor('#d5d5d5'); //设置画布宽度 canvasObj.setWidth(this.state.canvasWidth); //设置画布高度 canvasObj.setHeight(this.state.canvasHeight); //标识画布中元素选中时,是否还按原有的层级位置展示 canvasObj.preserveObjectStacking = true;/** * 设置元素选中框的样式 */ //边角节点背景透明 false fabric.Object.prototype.transparentCorners = false; //边角节点大小 fabric.Object.prototype.cornerSize = 6; //边框颜色 fabric.Object.prototype.borderColor = 'rgba(83,152,248,1)'; //角节点内部颜色 fabric.Object.prototype.cornerColor = 'white'; //角节点边框颜色 fabric.Object.prototype.cornerStrokeColor = 'rgba(83,152,248,1)';/** * 设置对象位置Left/Top的基准参考位置为自身中心点 * 默认 对象采用相对自身中心点旋转,即centeredRotation=true */ fabric.Object.prototype.originX = 'center'; fabric.Object.prototype.originY = 'center';this.editor = canvasObj; 4、画布事件监听//元素点击选中事件处理 canvasObj.on('selection:created', function(options) {//console.log('selection:created');//console.log(options);if (options.target) {// TODO} }//元素选中更新事件处理 canvasObj.on('selection:updated', function(options) {//console.log('selection:updated');//console.log(options);if (options.target) {// TODO} }//元素取消选中事件处理 canvasObj.on('selection:cleared', function(options) {//console.log('selection:cleared'); }//对象移动完毕事件处理 canvasObj.on('object:moved', function(options) {//console.log('moved');//console.log(options);if (options.target) {} }//对象旋转完成事件处理 canvasObj.on('object:rotated', function(options) {//console.log('rotated');//console.log(options);if (options.target) {// TODO} }//对象缩放完成事件处理 canvasObj.on('object:scaled', function(options) {//console.log('scaled');//console.log(options);if (options.target) {} }//对文本编辑修改后 canvasObj.on('text:changed', function(options) {//console.log('text:changed');//console.log(options);if (options.target) {} } 5、画布拖拽事件处理/** * 拖拽事件处理 start */ document.addEventListener('dragstart', function(e){//拖拽图片,并传递对象if(e.target.className == 'img'){scope.mouseX = e.offsetX;scope.mouseY = e.offsetY;//拖拽数据let sourceStr = e.target.dataset.source;if(sourceStr){scope.dragData = JSON.parse(sourceStr);}scope.figureType = e.target.className;} }, false);document.addEventListener('dragover', function(e){e.preventDefault(); }, false);//拖拽动作 this.dragObj('drop');dragObj(eventName){let scope = this;this.editor.on(eventName, function(opt){if((opt.e.target.className).trim() == 'upper-canvas' ){scope.dragEvt(eventName, opt);}}); }dragEvt(eventName, opt){let scope = this;if(eventName == 'dragover'){opt.e.preventDefault();}else if(eventName == 'drop'){//拖拽结束opt.e.preventDefault();//console.log(this.dragData);////对拖拽数据进行业务处理//} } /** * 拖拽事件处理 end */ 6、画布中的图片加载const dragImageUrl = this.dragData.imageUrl; fabric.Image.fromURL(dragImageUrl, function(image){image.set({id: getUUID(),left: imageLeft, top: imageTop,width: nodeWidth,height: nodeHeight,classname: 'img',source: scope.dragData,selectable,hasContorls}).scale(scope.state.canvasScale, scope.state.canvasScale).setCoords();//添加到画布scope.editor.add(image);//设置当前素材为选中状态scope.editor.setActiveObject(image);//重新渲染scope.editor.requestRenderAll(); }); 7、画布中的字体库加载//加载字体库数据, 默认load()方法 超时时长默认为3秒钟 loadAndUse(object, fontName, scope) {let myfont = new FontFaceObserver(fontName);myfont.load(null, 5000).then(function() {// when font is loaded, use it.if(object){object.source.fontFamily = fontName;object.set("fontFamily", fontName).setCoords();scope.editor.requestRenderAll();}}).catch(function(e) {console.log(e);alert('字体 ' + fontName + ' 加载失败。');}); }//字体方法的使用 this.loadAndUse(null, '宋体', this); 8、画布内容转换成图片保存到后台saveData(){... 省略其他代码 ...let paramData = new FormData();let dataUrl = this.editor.toDataURL();let blobImage = this.dataURLtoBlob(dataUrl);blobImage.contentType = 'application/octet-stream';paramData.append("file", blobImage);... 省略其他代码 ... }//数据类型转换 dataURLtoBlob(dataurl){let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);while(n--){u8arr[n] = bstr.charCodeAt(n);}return new Blob([u8arr], {type:'application/octet-stream'}); } 9、画布Canvas绘制的元素合并为一组将两个元素深深地绑定在一起,任何操作同时对两个有效,这里叫组的概念 const circle = new fabric.Circle({radius: 100,fill: '#eef',scaleY: 0.5,originX: 'center',originY: 'center' });const text = new fabric.Text('hello world', {fontSize: 30,originX: 'center',originY: 'center' });const group = new fabric.Group([ circle, text ], {left: 150,top: 100,angle: -10 }); 9、Canvas画布中将两个元素之间建立BOSS关系怎么理解就是将一个元素变为另一个元素的boss,boss元素拖动旋转操作,另一个元素跟着同样变,但是反过来就不行 bindMinionToBoss(canvas: fabric.Canvas, boss: fabric.Group): void {const minions = canvas.getObjects().filter((o: any) => o !== boss);const bossTransform = boss.calcTransformMatrix();const invertedBossTransform = fabric.util.invertTransform(bossTransform);minions.forEach((o: any) => {const desiredTransform = fabric.util.multiplyTransformMatrices(invertedBossTransform,o.calcTransformMatrix());o.relationship = desiredTransform;});boss.on("moving", () => {minions.forEach((o: any) => {if (!o.relationship) return;const newTransform = fabric.util.multiplyTransformMatrices(boss.calcTransformMatrix(),o.relationship);const opt = fabric.util.qrDecompose(newTransform);const point = new fabric.Point(opt.translateX, opt.translateY);o.setPositionByOrigin(point, "center", "center");o.set(opt);o.setCoords();});});} 其他详细Api请参见: http://fabricjs.com/docs/ 另外还有很多好玩有趣的功能等着我们去发现,可以参照官网的例子: http://fabricjs.com/demos/ 如果使用中出现常见问题,优先参考: http://fabricjs.com/fabric-gotchas 该文章在 2023/5/23 15:50:13 编辑过 |
关键字查询
相关文章
正在查询... |