强大的Canvas开源库Fabric.js简介与开发指南
什么是Fabric.js?
Fabric.js 是一個強大且簡單的Javascript HTML5 Canvas庫。
官網地址:http://fabricjs.com/
為什么要使用Fabric.js?
Canvas提供一個好的畫布能力, 但是Api不夠友好。繪制簡單圖形其實還可以, 不過做一些復雜的圖形繪制, 編寫一些復雜的效果,就不是那么方便了。Fabric.js就是為此而開發,它主要用對象的方式去編寫代碼。
Fabric.js能做的事情
在Canvas上創建、填充圖形(包括圖片、文字、規則圖形和復雜路徑組成圖形)。
給圖形填充漸變顏色。
組合圖形(包括組合圖形、圖形文字、圖片等)。
設置圖形動畫及用戶交互。
生成JSON、SVG數據等。
生成Canvas對象自帶拖拉拽功能。
它提供了靈活豐富的Api和可配置化參數輕松實現復雜的效果,該開源庫已被許多開發者用于項目實踐中,廣受好評。
下載趨勢圖
項目開發實戰
這里基于React框架為基礎,介紹Fabric.js開發實戰實例。
1、安裝Fabric.js
npm?install?fabric?--save 或 yarn add fabric官網還支持按需模塊定制構建,在你需要的特性模塊前面勾選,然后一鍵構建。這樣可以使得你整體的代碼量減少。
2、引入Fabric.js
import?{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元素拖動旋轉操作,另一個元素跟著同樣變,但是反過來就不行
其他詳細Api請參見:
http://fabricjs.com/docs/
另外還有很多好玩有趣的功能等著我們去發現,可以參照官網的例子:
http://fabricjs.com/demos/
如果使用中出現常見問題,優先參考:
http://fabricjs.com/fabric-gotchas
總結
以上是生活随笔為你收集整理的强大的Canvas开源库Fabric.js简介与开发指南的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 可能是最先出来的关于介绍使用Vue3的一
- 下一篇: 纯CSS实现React Logo图形,内