以前使用這個框架寫過一個卡片DIY的項目,中間遇到不少問題都只能經過google或github issues才能解決,國內資料較少,因此纔想寫這篇文章來簡單的作下總結,但願能夠幫到其餘人哈。javascript
附上我的項目地址:vue-card-diy 歡迎star~ ✨html
Fabric.js 是一個強大的H5 canvas框架,在原生canvas之上提供了交互式對象模型,經過簡潔的api就能夠在畫布上進行豐富的操做。vue
該框架是個開源項目,項目地址: githubjava
使用Fabric.js,你能夠在畫布上建立和填充對象; 好比簡單的幾何形狀 - 矩形,圓形,橢圓形,多邊形,自定義圖片或由數百或數千個簡單路徑組成的更復雜的形狀。 另外,還可使用鼠標縮放,移動和旋轉這些對象; 修改它們的屬性 - 顏色,透明度,z-index等。也能夠將畫布上的對象進行組合。下面我將會介紹我經常使用的功能以及場景,更多功能能夠參考 官方文檔git
npm install fabric --save
複製代碼
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>
複製代碼
首先在html頁面中寫一個350 x 200的canvas標籤, 這裏不寫寬高也行,後面能夠經過js來設置寬高github
<canvas id="canvas" width="350" height="200"></canvas>
複製代碼
初始化fabric的canvas對象,建立一個卡片(後面都用card
表示畫布對象)ajax
const card = new fabric.Canvas('canvas')
// ...這裏能夠寫canvas對象的一些配置,後面將會介紹
// 若是<canvas>標籤沒設置寬高,能夠經過js動態設置
card.setWidth(350)
card.setHeight(200)
複製代碼
就是這麼簡單,這樣就建立了一個基本的畫布。npm
官方提供了不少事件,如下爲經常使用的事件:json
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初始化時設置canvas
const card = new fabric.Canvas('canvas', {
backgroundColor: 'blue' // 畫布背景色爲藍色
});
// 或者
card.backgroundColor = 'blue';
// 或者
card.setBackgroundColor('blue');
複製代碼
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);
複製代碼
// 方式二(經過圖片路徑添加)
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);
複製代碼
框架提供瞭如 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
});
複製代碼
如轉載本文請註明文章做者及出處!