1、導語
我們想在畫布上畫個基本的簡單形狀的時候,使用 Canvas 不會覺得有什么繁瑣。但當畫布上需要任何形式的互動,繪制復(fù)雜的圖形和在特定情況需要改變圖片的時候,使用原生 canvas API 將會變得很困難。而fabric 旨在解決這個問題。


2、 安裝
yarn add fabric --save-dev? ?npm install fabric --save-dev
or
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"? async></script>
3、使用
<canvas id="canvas" width="300" height="300">
? ? ? 你的瀏覽器不支持 canvas,請升級你的瀏覽器
?</canvas>
3.1、繪制一個簡單的圖形
Fabric 提供了 7 種基礎(chǔ)形狀:
fabric.Circle (圓)
fabric.Ellipse (橢圓)
fabric.Line (線)
fabric.Polyline (多條線繪制成圖形)
fabric.triangle (三角形)
fabric.Rect (矩形)
fabric.Polygon (多邊形)
3.1.1
矩形
// 創(chuàng)建一個fabric實例
? ? let canvas = new fabric.Canvas("canvas"); //可以通過鼠標方法縮小,旋轉(zhuǎn)
? ? // or
? ? // let canvas = new fabric.StaticCanvas("canvas");//沒有鼠標交互的fabric對象
? ? // 創(chuàng)建一個矩形對象
? ? let rect = new fabric.Rect({
? ? ? left: 20, //距離左邊的距離
? ? ? top: 20, //距離上邊的距離
? ? ? fill: "green", //填充的顏色
? ? ? width: 200, //矩形寬度
? ? ? height: 200, //矩形高度
? ? });
? ? // 將矩形添加到canvas畫布上
? ? canvas.add(rect);
可以看到一個通過鼠標放大縮小且可以旋轉(zhuǎn)的綠色矩形

3.1.2?
圓和矩形
// 創(chuàng)建一個圓形對象
? ? let circle = new fabric.Circle({
? ? ? left: 0, //距離左邊的距離
? ? ? top: 0, //距離上邊的距離
? ? ? fill: "red", //填充的顏色
? ? ? radius: 50, //圓的半徑
? ? });
? ? // 創(chuàng)建一個三角形對象
? ? let triangle = new fabric.Triangle({
? ? ? left: 200, //距離左邊的距離
? ? ? top: 0, //距離上邊的距離
? ? ? fill: "blue", //填充的顏色
? ? ? width: 100, //寬度
? ? ? height: 100, //高度
? ? });
? ? // 將圖形形添加到canvas畫布上
? ? canvas.add(circle, triangle);

我們可以通過設(shè)置以下屬性,決定是否可以對相關(guān)元素進行交互
canvas.selection?=?false;?//?禁止所有選中
rect.set("selectable",?false);?//?只是禁止這個矩形選中
3.2、繪制圖片
主要是通過URL和img標簽繪制?
//通過url繪制圖片
fabric.Image.fromURL(
????//本地圖片需要通過require來引入,require("./xxx.jpeg")
????"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.thaihot.com.cn%2Fuploadimg%2Fico%2F2021%2F0711%2F1625982535739193.jpg&refer=http%3A%2F%2Fimg.thaihot.com.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1630940858&t=e1d24ff0a7eaeea2ff89cedf656a9374",
????(img)?=>?{
????????img.scale(0.5);
????????canvas.add(img);
????}
);
//也可以通過標簽繪制
let?img?=?document.getElementById("img");
let?image?=?new?fabric.Image(img,?{
????left:?100,
????top:?100,
????opacity:?0.8,
});
canvas.add(image);
3.3 通過自定義的路徑繪制
我們一起先看看幾個參數(shù)的含義
M : “move”移動到某點
L : “l(fā)ine”畫線 x,y
C : “curve”曲線
A : “arc”弧
z : 閉合路徑(類似 PS 中的創(chuàng)建選區(qū))
let?customPath?=?new?fabric.Path("M?0?0?L?300?100?L?170?100??z");
customPath.set({
????left:?100,
????top:?100,
????fill:?"green",
});
canvas.add(customPath);

可以看到通過路徑繪制,我們可以制作非常復(fù)雜的圖形(但是一般用不到,我們一般用它來解析 SVG 后拿到 path 復(fù)原圖形)
3.4 動畫
animate(param1,param2,param3)
param1:動畫的屬性
param2:動畫的最終位置
param3:可選對象(主要有如下屬性)
duration 默認為 500ms??梢杂脕砀淖儎赢嫷某掷m(xù)時間。
from 允許指定動畫屬性的起始值(如果我們不希望使用當前值)。
onComplete 動畫結(jié)束之后的回調(diào)。
easing 動效函數(shù)。很多內(nèi)置動畫效果, fabric.util.ease 下有一大堆動效的選項。常用的有easeOutBounce,easeInCubic,easeOutCubic,easeInElastic,easeOutElastic,easeInBounce?和?easeOutExpo等
絕對動畫
let?rect?=?new?fabric.Rect({
????left:?400,?//距離左邊的距離
????top:?200,?//距離上邊的距離
????fill:?"green",?//填充的顏色
????width:?200,?//寬度
????height:?200,?//高度
});
rect.animate("left",?100,?{
????onChange:?canvas.renderAll.bind(canvas),
????duration:?1000,
});
canvas.add(rect);

相對動畫
rect.animate("left", "+=100", {
? ? ? onChange: canvas.renderAll.bind(canvas),
? ? ? duration: 10000,
? ? });
rect.set({?angle:?45?});
rect.animate("angle",?"-=90",?{
onChange:?canvas.renderAll.bind(canvas),
duration:?2000,
});

3.5、 圖像濾鏡
目前 Fabric 為我們提供了以下內(nèi)置濾鏡
BaseFilter 基本過濾器
Blur 模糊
Brightness 亮度
ColorMatrix 顏色矩陣
Contrast 對比
Convolute 卷積
Gamma 伽瑪
Grayscale 灰度
HueRotation 色調(diào)旋轉(zhuǎn)
Invert 倒置
Noise 噪音
Pixelate 像素化
RemoveColor 移除顏色
Resize 調(diào)整大小
Saturation 飽和
圖像濾鏡
fabric.Image.fromURL("./aaa.jpeg",?(img)?=>?{
????img.scale(0.5);
????canvas.add(img);
});
fabric.Image.fromURL("./aaa.jpeg",?(img)?=>?{
????img.scale(0.5);
????//?添加濾鏡
????img.filters.push(new?fabric.Image.filters.Grayscale());
????//?圖片加載完成之后,應(yīng)用濾鏡效果
????img.applyFilters();
????img.set({
????????left:?300,
????????top:?250,
????});
????canvas.add(img);
});
3.6、顏色
無論你是使用十六進制,RGB 或 RGBA 顏色,F(xiàn)abric 都能處理的很好
定義顏色
new?fabric.Color("#f55");
new?fabric.Color("#aa3123");
new?fabric.Color("356333");
new?fabric.Color("rgb(100,50,100)");
new?fabric.Color("rgba(100,?200,?30,?0.5)");
顏色轉(zhuǎn)換
new?fabric.Color('#f55').toRgb();?//?"rgb(255,85,85)"
new?fabric.Color('rgb(100,100,100)').toHex();?//?"646464"
new?fabric.Color('fff').toHex();?//?"FFFFFF"
顏色疊加
let?redish?=?new?fabric.Color("#f55");
let?greenish?=?new?fabric.Color("#5f5");
redish.overlayWith(greenish).toHex();?//?"AAAA55"
redish.toGrayscale().toHex();?//?"A1A1A1"
3.7 漸變
Fabric 通過 setGradient 方法支持漸變,在所有對象上定義。調(diào)用 setGradient('fill', { ... })就像設(shè)置一個對象的“fill”值一樣。
let?circle?=?new?fabric.Circle({
??left:?100,
??top:?100,
??radius:?50
});
circle.setGradient("fill",?{
????//?漸變開始的位置
????x1:?0,
????y1:?0,
????//?漸變結(jié)束的位置
????x2:?circle.width,
????y2:?0,
????//漸變的顏色
????colorStops:?{
????????//?漸變的范圍(0,0.1,0.3,0.5,0.75,1)0-1之間都可以
????????0:?"red",
????????0.2:?"orange",
????????0.4:?"yellow",
????????0.6:?"green",
????????0.8:?"blue",
????????1:?"purple"
????},
});

3.8、事件
fabric 中通過 on 方法來初始化事件,off 方法用來刪除事件。
常用的事件有以下
“mouse:down” 鼠標被按下
“object:add” 對象被添加
“after:render” 渲染完成
還有一大堆:
鼠標事件:“mouse:down” ,“mouse:move”和“mouse:up...” 選擇相關(guān)的事件:“before:selection:cleared”, “selection:created”, 詳細的可以查看 官方文檔
canvas.on("mouse:down",function(options){
canvas.clear();
lettext?=newfabric.Text("你點我啦~",?{
left:200,
top:200,
});
canvas.add(text);
console.log(options.e.clientX,?options.e.clientY);
});
canvas.on("mouse:up",function(options){
this.text?="你沒點我0.0";
canvas.clear();
lettext?=newfabric.Text("你沒點我0.0",?{
left:200,
top:200,
});
canvas.add(text);
console.log(options.e.clientX,?options.e.clientY);
});
Fabric 允許將偵聽器直接附加到 canvas 畫布中的對象上。
let rect = new fabric.Rect({ width: 100, height: 50, fill: "green" });
? ? rect.on("selected", function () {
? ? ? console.log("哦吼~你選擇了我 rect");
? ? });
? ? canvas.add(rect);
? ? circle.on("selected", function () {
? ? ? console.log("哈哈哈~你選擇了我");
? ? });
3.9、自由繪畫
Fabric canvas 的 isDrawingMode 屬性設(shè)置為 true 即可實現(xiàn)自由繪制模式.
這樣畫布上的點擊和移動就會被立刻解釋為鉛筆或刷子。
let canvas?=new fabric.Canvas("canvas");
canvas.isDrawingMode?=true;
canvas.freeDrawingBrush.color?="blue";
canvas.freeDrawingBrush.width?=5;
最后
很開心寫下這篇文章,它是我近期接觸到的項目中用到的一個很強大的canvas庫,所以有了這個契機就系統(tǒng)性的了解熟悉一下它的相關(guān)使用,希望能對你有所幫助。
參考教程
官網(wǎng)鏈接:https://gitee.com/eternitywith/fabric.js-docs-cn
CDN:http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js
github: https://github.com/Rookie-Birds/Fabric-Tutorial_zh-CN
參考文章:
https://segmentfault.com/a/1190000038688093
https://juejin.cn/post/6844903773945462792