動態海報營銷FabricJs方案

簡介

Fabric.js是一個可以簡化Canvas程序編寫的庫。 Fabric.js爲Canvas提供所缺少的對象模型, svg parser, 交互和一整套其他不可或缺的工具。Fabric.js可以做很多事情,如下:

  • 在Canvas上創建、填充圖形(包括圖片、文字、規則圖形和複雜路徑組成圖形)。
  • 給圖形填充漸變顏色。
  • 組合圖形(包括組合圖形、圖形文字、圖片等)。
  • 設置圖形動畫集用戶交互。
  • 生成JSON, SVG數據等。
  • 生成Canvas對象自帶拖拉拽功能。

使用教程

安裝

npm 安裝

npm install fabric --save

cdn引用

<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>// 貌似國外相對較慢

可以在https://www.bootcdn.cn/fabric... 找到更快的CDN來源

在使用前,先看下我做的總體效果如下:
4.jpg

初始化

創建了一個基本的畫布

<canvas id="canvas" width="350" height="200"></canvas>
const card = new fabric.Canvas('canvas') 

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

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

對畫布的交互

常用監聽事件如下:

  • mouse:down:鼠標按下時
  • mouse:move:鼠標移動時
  • mouse:up:鼠標擡起時
    var canvas = new fabric.Canvas('canvas');
    canvas.on('mouse:down', function(options) {
        console.log(options.e.clientX, options.e.clientY)
    })

監聽畫布對象事件以便“上下一步”的神操作

以下爲常用的事件:

  • object:added 添加圖層
  • object:modified 編輯圖層
  • object:removed 移除圖層
  • selection:created 初次選中圖層
  • selection:updated 圖層選擇變化
  • selection:cleared 清空圖層選中

1.jpg

下面是原文,更多參考__fabricjs官網事件__:

So which other events are available in Fabric? Well, from mouse-level ones there are "mouse:down", "mouse:move", and "mouse:up". From generic ones, there are "after:render". Then there are selection-related events: "before:selection:cleared", "selection:created", "selection:cleared". And finally, object ones: "object:modified", "object:selected", "object:moving", "object:scaling", "object:rotating", "object:added", and "object:removed"

設置畫布背景

// 讀取圖片地址,設置畫布背景
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();
});

向畫布添加圖層對象

fabric.js提供了很多對象,除了基本的 Rect,Circle,Line,Ellipse,Polygon,Polyline,Triangle對象外,還有如 Image,Textbox,Group等更高級的對象,這些都是繼承自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);
/**
* 如何向畫布添加一個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
})

常規操作

this.selectedObj.rotate(angle); //旋轉圖層
this.selectedObj.set({

scaleX: -this.selectedObj.scaleX, // 水平翻轉

})
card.remove(this.selectedObj) // 傳入需要移除的object
this.selectedObj.bringForward();// 上移圖層
this.selectedObj.sendBackwards();// 下移圖層
card.moveTo(object, index);// 也可以使用canvas對象的moveTo方法,移至圖層到指定位置

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

手機相冊拍照圖片尺寸太大導致拖動麻煩

主要是在添加圖片對象的時候,有兩個參數可以應用起來,分別是scaleX,scaleY參數,通過這兩個參數,可以對應地縮放圖片大小,方便圖片能完整地在canvas畫布體現出來。

先將手機圖片加載完畢,算出寬和高,根據自己的畫布縱橫對比重新算出 圖片的縮放參數即可。

          new Promise(function(res,rej){
              let img = new Image();
              img.onload = function(){
                 console.log(img.width,img.height);
                 res([img.width,img.height]);
              }
              img.src = file.content;
          }).then(function(response){
              let width = response[0];
              let height = response[1];
              let xYRet = 0.61;    //300/490  縱橫對比
              let targetRepix = 1;

              if(height > 490)
              {
                targetRepix = (490/height).toFixed(2);
              }

              if(width > 300)
              {
                targetRepix = (300/width).toFixed(2);
              }


              fabric.Image.fromURL(file.content, (img) => {
                  img.set({
                      top:30,
                      left:30,
                      scaleX: targetRepix, 
                      scaleY: targetRepix,
                      hasControls: true, // 是否開啓圖層的控件
                      borderColor: 'orange', // 圖層控件邊框的顏色
                  });
                  // 添加對象後, 如下圖
                  card.add(img);
              });
          })

文字粗細和顏色隨意設

//其中selectedObj 是當前選中的文字對象

    this.selectedObj.set({
        fontWeight:xxx  //改變粗細
    });

    this.selectedObj.set({
        fill:xxx    //改變顏色
    });

2.jpg

3.png

更改選中對象的框樣式

        card.on('selection:updated', (e) => {
          console.log('selection:updated', e.target)
          this.setSelectedObj(e.target)

            //通過選中的對象更改樣式
            e.target.set({
                transparentCorners: false,
                cornerColor: 'blue',
                cornerStrokeColor: 'red',
                borderColor: 'red',
                cornerSize: 12,
                padding: 10,
                cornerStyle: 'circle',
                borderDashArray: [3, 3]
            });

        })

效果如下圖:

6.jpg

畫布序列化與反序列化————記錄狀態記錄

框架提供瞭如 toJSON 和 loadFromJSON 方法,作用分別爲導出當前畫布的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
});
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章