Painter是由酷家樂移動前端團隊打造的一款小程式繪圖元件。
原專案地址:github.com/Kujiale-Mob…
這款互動版原來是為了針對業務中的新需求而由我自己開發的,後來需求改動,所以並沒有用上。組裡大佬考慮種種原因(主要是專案沒用上,=0=~~),讓我先在自己的github上開源。這版painter與原版的區別在於:
- 新增了互動事件。Painter本質是以canvas為基礎的,小程式的canvas有許多限制。允許canvas上元素的互動點選事件,可以實現更為便捷的功能,比如原來需要在canvas上新增功能按鈕,現在可以直接畫在canvas上
- 新增拖拽元素的功能。目前這個功能沒有完善好,因為它的滑動動作會與小程式的全屏滑動事件衝突,因此,拖拽功能在固定的頁面上效果才好,如在拖拽時設定overflow: hidden等。
這裡將新版的Painter稱為dancing-painter。引入方式請參考readme和demo。
演示:
主要功能:
指原版的painter的功能。這些功能依然是本專案的主(實)要(用)功能。
簡介:
原版的使用簡介請參見 juejin.im/post/5b40b1…
簡單來講,使用過程如下圖所示,可以結合demo來看:
距離首次開源Painter庫已經有一段時間了,這期間獲益於各路道友的幫助和提點,Painter進行了幾波更新(原專案地址):
新增特性:
- 增加align屬性,可以使任意元素可以實現左中右對齊。
- 加入文字換行的能力。對一段文字設定width或者maxLines,都有可能觸發文字的換行。
- 新增文字的一些屬性:fontWeight, textDecoration, textStyel(fill, stroke), maxLines, lineHeight
- 圖片mode屬性,實現圖片裁剪、縮放,預設為aspectFill
- 圖片不設定width, heighti屬性,使用預設寬高
- left, right, top, bottom對負數的支援
修復問題:
- 某些機型上切邊會出現黑線。
- 安卓機型上圓角無法顯示
- 使用檔案前檢查檔案是否正常
- 二維碼大小顯示異常
互動功能:
這一版的特色主要是具備元素的點選事件實現以及拖拽功能,做出來以後因為專案上暫時用不上,所以感覺功能上可能比較雞肋。不過還蠻好玩的?
在demo中稱之為dancing-painter。
**強調:**要使用互動功能,有一下兩點需要注意:
- 匯入palette時,使用絕對路徑方法匯入
- palette類,以module.exports輸出。
原因:小程式頁面向元件傳值時,會把物件引數做一個類似於JSON.parse(JSON.stringfy())的拷貝,導致物件中的函式在傳遞後丟失。因此在dancing-painter中,選擇講palette(即生成圖片的json程式碼)的路徑傳遞給painter元件,在元件內require到這個檔案,再合成所需的json資料。
匯入程式碼如下:
//直接匯入資料
// const template = new DCard().palette();
//匯入絕對路徑
const template = {
path: '/palette/dancing-card.js',
data: {},
};
this.setData({
template: template,
});
複製程式碼
palette:
//位於/palette/dancing-card.js
class PaletteCard {
context = {}
constructor(data) {
this.data = data;
}
palette() {
return{
...
}
}
}
module.exports = PaletteCard;
複製程式碼
實現點選效果
Painter的元素繪製是以json的形式給出的,其互動行為和拖拽效果也定義在相應的json檔案裡。
在需要設定某一個元素的點選事件的時候,只需要在其相應的json程式碼里加入methods屬性即可。該屬性支援一下幾種點選方式:
name | description |
---|---|
tap | 點選 |
longpress | 長按 |
touchstart | 開始觸控 |
touchmove | 移動 |
touchend | 觸控結束 |
每一個方法可以返回一個boolean值,以表示是否攔截該事件。在dancing-painter中,如果在頁面上元素有重疊,則方法的傳遞預設是由下而上的;在任意一個元素的methods方法中,可以返回true來攔截該事件。
使用拖拽功能
使用animation屬性,目前只支援拖拽能力。由於存在與螢幕的滑動衝突(如果有大神知道怎麼截獲螢幕的滑動事件,如長頁面的滾動,請千萬不吝賜教告訴我哈),需要在使用時固定住整個頁面,如設定overflow: hidden。
使用:設定animation:{drag:true}
示例:
{
width: '700rpx',
height: '1000rpx',
background: '#eee',
views: [{
type: 'qrcode',
content: 'https://github.com/Kujiale-Mobile/Painter',
css: {
top: '40rpx',
left: '180rpx',
color: 'red',
borderWidth: '10rpx',
borderColor: 'blue',
width: '120rpx',
height: '120rpx',
align: 'center',
},
methods: {
tap() {
console.log('qrcode');
},
}
},
{
type: 'rect',
css: {
top: '40rpx',
left: '180rpx',
color: 'green',
borderRadius: '20rpx',
borderWidth: '10rpx',
width: '120rpx',
height: '120rpx',
},
methods: {
tap() {
// 呼叫當前頁面的function方法
const pages = this.getCurrentPages();
const currentPage = pages[pages.length-1];
currentPage.function();
},
},
animation: {
drag: true,
},
}]
}
複製程式碼
事件冒泡
事件預設是冒泡傳遞的。示例如下:
上面的程式碼中是兩個部分重疊的二維碼和方形:
點選二者的重合部分,控制檯輸出:
效能
拖拽功能是一種動畫現象,涉及到canvas的重繪。經過測試,在IDE上重繪速度很快,在真機上有數量級的差別。
動畫效果的連貫性主要是由canvas.draw()的速度決定的。
下圖展示了在demo主頁上,canvas.draw()方法在ide和真機上執行的時間差別(單位:ms):
IDE: 真機(華為榮耀8):
結語
感謝大佬在開發中對我的無限幫助。
感謝 demi520 的 wxapp-qrcode 庫,Painter 中二維碼繪製部分使用了該庫的部分程式碼,並做了些修改。
另外這裡有一篇wiki簡單介紹了怎樣在mpvue中使用Painter。
坑::mpvue在更新某一個頁面元素的值的時候,會同時把所有data中存在的元素都更新一遍。
這就造成了這個問題:Painter繪製完成後,會觸發onImgOK函式,傳出圖片的url。這時將該url傳入某image的src中去,同時就會觸發Painter的template的再賦值,從而導致無限重繪。
最後,作為程式設計師屆的新手和菜鳥,誠邀各路大神用issue和建議砸死我?
最後,作為程式設計師屆的新手和菜鳥,誠邀各路大神用issue和建議砸死我?
最後,作為程式設計師屆的新手和菜鳥,誠邀各路大神用issue和建議砸死我?