使用Fabric.js玩轉H5 Canvas

前言

之前使用這個框架寫過一個卡片DIY的項目,中間遇到很多問題都只能通過google或github issues才能解決,國內資料較少,所以纔想寫這篇文章來簡單的做下總結,希望可以幫到其他人哈。

附上個人項目地址:vue-card-diy 歡迎star~ ✨

什麼是Fabric.js?

Fabric.js 是一個強大的H5 canvas框架,在原生canvas之上提供了交互式對象模型,通過簡潔的api就可以在畫布上進行豐富的操作。

該框架是個開源項目,項目地址: github

Fabric.js有什麼功能?

使用Fabric.js,你可以在畫布上創建和填充對象; 比如簡單的幾何形狀 - 矩形,圓形,橢圓形,多邊形,自定義圖片或由數百或數千個簡單路徑組成的更復雜的形狀。 另外,還可以使用鼠標縮放,移動和旋轉這些對象; 修改它們的屬性 - 顏色,透明度,z-index等。也可以將畫布上的對象進行組合。下面我將會介紹我常用的功能以及場景,更多功能可以參考 官方文檔

安裝

npm安裝

npm install fabric --save

通過cdn引用

<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>

初始化

首先在html頁面中寫一個350 x 200的canvas標籤, 這裏不寫寬高也行,後面可以通過js來設置寬高

<canvas id="canvas" width="350" height="200"></canvas>

初始化fabric的canvas對象,創建一個卡片(後面都用card表示畫布對象)

const card = new fabric.Canvas('canvas') 

// ...這裏可以寫canvas對象的一些配置,後面將會介紹

// 如果<canvas>標籤沒設置寬高,可以通過js動態設置
card.setWidth(350)
card.setHeight(200)

就是這麼簡單,這樣就創建了一個基本的畫布。

開始花樣操作

監聽畫布上的事件

官方提供了很多事件,以下爲常用的事件:

  • object:added 添加圖層
  • object:modified 編輯圖層
  • object:removed 移除圖層
  • selection:created 初次選中圖層
  • selection:updated 圖層選擇變化
  • selection:cleared 清空圖層選中
// 在canvas對象初始化後,通過以下方式監聽
// 比如監聽畫布的圖層編輯事件
card.on('object:modified', (e) => {
    console.log(e.target) // e.target爲當前編輯的Object
    // ...旋轉,縮放,移動等編輯圖層的操作都監聽到
    // 所以如果有撤銷/恢復的場景,這裏可以保存編輯狀態
});

設置畫布背景

// 讀取圖片地址,設置畫布背景
fabric.Image.fromURL('xx/xx/bg.jpg', (img) => {
  img.set({
   // 通過scale來設置圖片大小,這裏設置和畫布一樣大
    scaleX: card.width / img.width,
    scaleY: card.height / img.height,
  });
  // 設置背景
  card.setBackgroundImage(img, card.renderAll.bind(card));
  card.renderAll();
});

如果要設置畫布的背景顏色,可以在canvas初始化時設置

const card = new fabric.Canvas('canvas', {
  backgroundColor: 'blue' // 畫布背景色爲藍色
});

// 或者
card.backgroundColor = 'blue';

// 或者
card.setBackgroundColor('blue');

向畫布添加圖層對象

fabric.js提供了很多對象,除了基本的 RectCircleLineEllipsePolygonPolylineTriangle對象外,還有如 ImageTextboxGroup等更高級的對象,這些都是繼承自Fabric的Object對象

下面我就介紹如何添加圖片和文字,其他對象大同小異

/**
* 如何向畫布添加一個Image對象?
*/

// 方式一(通過img元素添加)
const imgElement = document.getElementById('my-image');
const imgInstance = new fabric.Image(imgElement, {
  left: 100, // 圖片相對畫布的左側距離
  top: 100, // 圖片相對畫布的頂部距離
  angle: 30, // 圖片旋轉角度
  opacity: 0.85, // 圖片透明度
  // 這裏可以通過scaleX和scaleY來設置圖片繪製後的大小,這裏爲原來大小的一半
  scaleX: 0.5, 
  scaleY: 0.5
});
// 添加對象後, 如下圖
card.add(imgInstance);

// 方式二(通過圖片路徑添加)
fabric.Image.fromURL('xx/xx/vue-logo.png', (img) => {
  img.set({
    hasControls: false, // 是否開啓圖層的控件
    borderColor: 'orange', // 圖層控件邊框的顏色
  });
  // 添加對象後, 如下圖
  canvas.add(img);
});

/**
* 如何向畫布添加一個Textbox對象?
*/

const textbox = new fabric.Textbox('這是一段文字', {
    left: 50,
    top: 50,
    width: 150,
    fontSize: 20, // 字體大小
    fontWeight: 800, // 字體粗細
    // fill: 'red', // 字體顏色
    // fontStyle: 'italic',  // 斜體
    // fontFamily: 'Delicious', // 設置字體
    // stroke: 'green', // 描邊顏色
    // strokeWidth: 3, // 描邊寬度
    hasControls: false,
    borderColor: 'orange',
    editingBorderColor: 'blue' // 點擊文字進入編輯狀態時的邊框顏色
});
// 添加文字後,如下圖
card.add(textbox);

獲取當前選中的圖層對象

// 方式一
this.selectedObj = card.getActiveObject(); // 返回當前畫布中被選中的圖層 

// 方式二
card.on('selection:created', (e) => {
    // 選中圖層事件觸發時,動態更新賦值
    this.selectedObj = e.target
})

旋轉圖層

// 順時針90°旋轉
const currAngle = this.selectedObj.angle; // 當前圖層的角度
const angle = currAngle === 360 ? 90 :currAngle + 90;
this.selectedObj.rotate(angle);
// 如果是通過滑塊的方式控制旋轉
// this.selectedObj.rotate(slideValue);

// 所有圖層的操作之後,都需要調用這個方法
card.renderAll()

翻轉圖層

// 水平翻轉,同理垂直翻轉改爲scaleY屬性
this.selectedObj.set({
    scaleX: -this.selectedObj.scaleX,
})

card.renderAll()

移除圖層

card.remove(this.selectedObj) // 傳入需要移除的object
card.renderAll()

控制畫布上的圖層層級

向畫布添加圖層,默認是依次往上疊加,但是當你選中一個圖層進入active狀態時,該圖層會默認置於頂層,如果像禁止選中圖層時指定,可以:

// 在畫布初始化後設置
card.preserveObjectStacking = true // 禁止選中圖層時自定置於頂部

設置之後,我選中vue logo就是這個樣子,不會置頂。

如何上移和下移圖層?

// 上移圖層
this.selectedObj.bringForward();

// 下移圖層
this.selectedObj.sendBackwards();

// 也可以使用canvas對象的moveTo方法,移至圖層到指定位置
card.moveTo(object, index);

畫布狀態記錄

框架提供瞭如 toJSONloadFromJSON 方法,作用分別爲導出當前畫布的json信息,加載json畫布信息來還原畫布狀態。

// 導出當前畫布信息
const currState = card.toJSON(); // 導出的Json如下圖

// 加載畫布信息
card.loadFromJSON(lastState, () => {
  card.renderAll();
});

將畫布導出成圖片

const dataURL = card.toDataURL({
  format: 'jpeg', // jpeg或png
  quality: 0.8 // 圖片質量,僅jpeg時可用
  // 截取指定位置和大小
  //left: 100, 
  //top: 100,
  //width: 200,
  //height: 200
});

Fabric.js的基本介紹就到這裏,這個框架很強大,還有很多功能可以去試試,歡迎大家評論交流哈!

如轉載本文請註明文章作者及出處!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章