iT邦幫忙

2024 iThome 鐵人賽

DAY 5
0
Modern Web

一起來玩圖像編輯器:Fabric.js 的實戰修煉系列 第 5

Day5- 來概念解構 Fabric.js 吧 (3)-事件(events)與生命週期

  • 分享至 

  • xImage
  •  

事件系統(events)

Fabric.js有一個強大的事件系統,允許監聽和響應各種畫布和物件事件,很像 javascript 的事件一樣,可以加上跟移除監聽器,並且有 fire() 讓我們可以自己定義觸發事件的時機。

由這三種構成:

  • on(): 綁定事件監聽器
  • off(): 移除事件監聽器
  • fire(): 觸發自定義事件

on(): 綁定事件監聽器

當指定事件發生時,會調用綁定的回調函數(會執行你綁定的 function)。

var canvas = new fabric.Canvas('my-canvas');

var moveHandler = function () {
    console.log("我正在移動 object!");
};

var modifiedHandler = function () {
    console.log("我正在更改 object!");
};

var customEvtHandler = function () {
    console.log("這是我客製化的事件");
};

// 可以這樣寫
canvas.on('object:moving', moveHandler);
canvas.on('object:modified', modifiedHandler);
canvas.on('custom:event', customEvtHandler);

//也可以這樣寫在一起
canvas.on({
    'object:moving' : moveHandler,
    'object:modified' : modifiedHandler,
    'custom:event' : customEvtHandler
});

off(): 移除事件監聽器

用於移除之前綁定的事件監聽器。

// 跟 添加事件監聽器一樣,怎麼加就怎麼移除
// 可以這樣寫
canvas.off('object:moving', moveHandler);
canvas.off('object:modified', modifiedHandler);
canvas.off('custom:event', customEvtHandler);

//也可以這樣寫在一起
canvas.off({
    'object:moving' : moveHandler,
    'object:modified' : modifiedHandler,
    'custom:event' : customEvtHandler
});

我們通常會這樣在 React 中使用 useEffect 來處理 fabric.js 事件

  1. 在 useEffect 中,我們初始化 fabric.Canvas 並註冊 mouse:over 和 mouse:out 事件。
  2. 在 useEffect 的清理函數中,我們移除這些事件監聽器,以避免內存洩漏。
import React, { useEffect, useRef } from 'react';
import { fabric } from 'fabric';

const FabricCanvas = () => {
  const canvasRef = useRef(null);

    const handleMouseOver = () => {
      console.log('滑鼠滑進 canvas ~');
    };

    const handleMouseOut = () => {
      console.log('滑鼠離開 canvas ~');
    };
	
  useEffect(() => {
    const canvas = new fabric.Canvas(canvasRef.current);
    
    // 註冊事件
    canvas.on('mouse:over', handleMouseOver);
    canvas.on('mouse:out', handleMouseOut);

    // 清理事件
    return () => {
      canvas.off('mouse:over', handleMouseOver);
      canvas.off('mouse:out', handleMouseOut);
    };
  }, []);

  return <canvas ref={canvasRef} width={800} height={600} />;
};

export default FabricCanvas;

fire(): 觸發自定義事件

fire() 方法用於手動觸發指定事件,並可選擇傳遞一些數據給事件處理器。

// 觸發自訂事件的時候使用 fire
canvas.fire('custom:event', { someData: '這裡可以額外加入一些要記錄的資訊' });

var customEvtHandler = function(event) {
  console.log('Custom event detected!', event.someData); 
  // 可以從 event.someData 呼叫出事件發生當下你所記錄的資料
  //在這裏就是 '這裡可以額外加入一些要記錄的資訊' 
}

// 呼叫的方式也是跟其他預設的 event 一樣
canvas.on('custom:event', customEvtHandler);

以下是目前存在的事件列表及其介紹:

一般事件 (General)

  • after:render:渲染後連續觸發。
  • before:render:渲染前觸發。
  • canvas:cleared:調用 canvas.clear() 後觸發。

滑鼠相關事件 (Mouse related)

  • mouse:over:滑鼠移動到畫布上時觸發。
  • mouse:out:滑鼠移出畫布時觸發。
  • mouse:down:在畫布上發生 mousedown 事件時觸發。
  • mouse:up:在畫布上發生 mouseup 事件時觸發。
  • mouse:move:滑鼠在畫布上移動時觸發。
  • mouse:wheel:使用滾輪時觸發。

物件相關事件 (Object related)

  • object:added:物件被添加後觸發。
  • object:modified:物件被修改(移動、縮放、旋轉)後觸發。
  • object:moving:物件移動過程中連續觸發。
  • object:over:滑鼠移到物件上時觸發。
  • object:out:滑鼠移出物件時觸發。
  • object:removed:物件被移除後觸發。
  • object:rotating:物件旋轉過程中連續觸發。
  • object:scaling:物件縮放過程中連續觸發。
  • object:selected:物件被選中時觸發。

路徑相關事件 (Path related)

  • path:created:自由繪製的路徑被創建時觸發。

選取區域事件 (Selection related)

  • before:selection:cleared:選取區域被清除前(active狀態被銷毀前)觸發。
  • selection:cleared:選取區域被清除後(active狀態被銷毀後)觸發。
  • selection:created:選取區域被創建後(active狀態被創建後)觸發。

文字相關事件 (Text related)

  • text:editing:entered:進入文字編輯模式時觸發。
  • text:editing:exited:退出文字編輯模式時觸發。
  • text:selection:changed:文字選取變更時觸發。
  • text:changed:文字內容變更時觸發。

官方 events demo

實際玩玩看更好理解:
Fabric.js demos · Event inspector


Fabric.js 的生命週期

Fabric.js 的生命週期可以分為以下幾個主要階段:

初始化階段:

創建 fabric.Canvas 實例並綁定到 HTML 元素。
設置畫布的基本屬性(如寬度、高度、背景色等)。

物件創建階段:

使用 fabric.Object 的子類(如 fabric.Rect, fabric.Circle, fabric.Text 等)創建圖形物件。
設置物件的屬性(如位置、大小、顏色等)。

物件添加階段:

將創建的物件添加到畫布上,
需要調用 canvas.renderAll() 方法來重新渲染畫布,才能看到物件確實被添加上去的畫面。

事件處理階段:

註冊事件處理器來處理用戶交互(如 mouse:down, object:modified 等)。
事件處理器可以用來更新物件的屬性或觸發其他操作。

渲染階段:

當物件的屬性發生變化時,調用 canvas.renderAll() 方法來重新渲染畫布。
Fabric.js 會自動處理畫布的渲染,確保所有物件都正確顯示。

清理階段:

當不再需要使用畫布時,清理資源以避免內存洩漏。
可以使用 canvas.dispose() 方法來清理畫布和所有相關資源。

*需要注意的是當物件的屬性發生變化時(如位置、大小、顏色等),需要調用 canvas.renderAll() 方法來重新渲染畫布。
⇛ 簡言之,只要用程式碼改變了屬性,就需要重新render,才能把改變的東西印在畫面上


上一篇
Day4-來概念解構 Fabric.js 吧 (2)-物件導向特性與物件(Object)與擴展機制(extend)
下一篇
Day6- 小小介紹 Fabric.js 的歷史沿革
系列文
一起來玩圖像編輯器:Fabric.js 的實戰修煉30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言