微信小程式朋友圈分享圖片生成方案實現

生忘發表於2019-03-03
微信小程式朋友圈分享圖片生成方案實現

在小程式界裡,生成圖片分享到朋友圈這個功能,是如此得光芒耀眼,以至於各個小程式都趨之若鶩地前來跪倒在她的石榴裙下。不幸的是,微信爸爸並沒有提供給我們很好很便捷的相關工具;恰恰相反,螢幕截圖的功能被殘忍丟進歷史的垃圾桶,只留下一個Canvas元件以及圍繞在其周圍的深淵巨坑們。

所以我們準備了一套名為Painter的工具, 為開發者提供一種簡單實用的“繪製”圖片的解決思路,讓開發者可以自由地生成自己想要的圖片檔案。

github傳送門:github.com/Kujiale-Mob…

如果直接使用canvas進行繪圖,那絕對是很酸爽的一次體驗,除了失控的程式碼,還有無數的天坑。先來列舉一下canvas 中踩過的坑以及我們的解決(或繞過)的方法。

canvas的坑

painter從實現上來講,是用了小程式的canvas作為載體來實現以上功能的。而canvas有很多著名的坑。有的坑,我們小心翼翼地繞了過去;有的坑,我們還是痛快淋漓地一腳踩了下去……

  1. 在微信版本6.6.6的某些ios機型上,canvas的clip()方法不能被restore。導致在這些機型上無法進行切圓角的操作。迫於無奈在開發中我們不得已拋棄了這些機型,用了一個if語句將這些機器的切圓角功能閹割了。。。
  2. 小程式的canvas提供了measuretText()方法,暫時只支援測量文字寬度,無法知道文字的具體高度。因此一些元素對齊的需求無法做到很漂亮。
  3. 在繪製圖片的時候,有機率會發生很神奇的表現,即canvas繪圖的時候位置出現整體偏差,造成最後生成的圖片有殘缺。這種情況大多數時候發生在onLoad中呼叫painter的情況下。我們處理的方法是對圖片的寬和高比例進行檢測,一旦出現異常,就重新繪製一遍。
  4. canvas不能繪製網路圖片。canvas.drawImage(url)方法,給url傳入一個網路連結,在模擬器上表現完美,然而在真機上無法繪製。我們在Painter中引入了一套自己的網路圖片下載後繪製的機制,並在其中加入了LRU儲存管理機制。
  5. canvas是原生元件,始終位於檢視的最上層,z-index設定對其無效。這個就不多說了。。很多人應該都踩過。
  6. canvas要進行繪製,則canvas元件必須真實地被寫在頁面上,而且其wx:if不能為false。不過,允許把canvas元件放置在螢幕之外,如設定position:fixed;left:750rpx;。這一方法是可以解決5,6兩點問題的黑科技

Painter的功能

微信小程式朋友圈分享圖片生成方案實現

如圖所示

通過右邊的類似於css又有點像json但其實上它是個js的寥寥幾行程式碼,我們繪製出了左邊的這樣的圖形,包含了背景圖片、文字、圖片、二維碼這四種常用的元素。

Painter閱讀完程式碼,繪製成圖片以後,會將圖片的連結返回給我們。此時,我們可以將圖片上傳、儲存到本地或者顯示在螢幕上。

它可以很方便地定製所需要的圖片,還可以自由動態地給圖片更換風格。

此外,小程式canvas.drawImage()方法在真機上不能繪製網路圖片。而Painter 可以解決這個問題,如果有繪製網路圖片的需求也可以考慮使用Painter。

Painter其它優勢

  1. painter可以下載網路圖片到本地,並對下載到本地的網路內容進行LRU管理。目前小程式允許的最大本地儲存為10m,我們預設painter可使用的本地儲存為6m,超出時會對本地儲存進行清理。如果需要自定義,可以在/painter/lib/downloader.js中修改MAX_SPACE_IN_B屬性。

  2. 目前子 view 的 css 屬性支援 object 或 array。允許將幾個view公用的css屬性提取出來。

  3. 由於palette 是以 js 承載的 json,所以你可以在每一個屬性中很方便的加上自己的邏輯。也可以把某些屬性單獨提取出來,讓多個 palette 共用,做到模組化。

使用

demo下載

demo專案使用submodule的方式進行管理,因此在clone時需要執行

git clone https://github.com/Kujiale-Mobile/Painter.git --recursive
複製程式碼

clone完成後可以看到目錄。其中,/pages/example中存放的是使用示例,/components/painter就是我們所引入的功能元件。此外還有一個palette目錄,裡面存放是我們所需要繪圖程式碼。實際工作時,painter會調取card.js裡的資訊,在圖片上繪製出相應的圖形,就像一支畫筆在調色盤上調製蘸取了顏料,然後在畫布上創作一樣。

微信小程式朋友圈分享圖片生成方案實現

將Painter引入到自己的專案

你可以直接將demo裡的painter複製貼上到自己的專案下,當然也可以更為優雅地執行一下這個程式碼:

git submodule add https://github.com/Kujiale-Mobile/PainterCore.git painter
複製程式碼

它會將Painter工具放置在你當前的目錄下。我們推薦的做法是把它放在你的components下。

引入元件

像其它的元件一樣,在需要引入Painter的頁面.json檔案中新增:

"usingComponents":{
  "painter":"/components/painter/painter"
}
複製程式碼

元件呼叫

在頁面的xml檔案中呼叫painter元件,並傳入pallete規則的資料,以及繪製結束以後的回撥。

<painter palette="{{data}}" bind:imgOK="onImgOK" bind:imgErr="onImgErr"/>
複製程式碼

palette即是我們的調色盤資料,以json形式根據一定規範建立,詳細資訊請移步下文。

繪製回撥

bind:imgOK="onImgOK"
bind:imgErr="onImgErr"
複製程式碼

資料傳入後,painter就會開始繪製,無論繪製成功或是失敗,都能在相應的回撥方法裡獲取相關的資訊,如:

微信小程式朋友圈分享圖片生成方案實現 微信小程式朋友圈分享圖片生成方案實現

Pallette

說到底,Painter是一支畫筆工具,具體要讓這支畫筆畫什麼東西,還得由我們,天資聰穎的程式猿們,來告訴它。告訴它應該畫什麼,在哪裡畫,畫的時候用什麼姿勢……等等。這需要用一些別的手段,因為科學的實驗證明過,試圖用普通話這門語言跟它進行溝通,是不會有任何效果的。

調色盤屬性

每一塊調色盤都它自己的整體屬性,它一般規定了整個繪圖範圍的大小、樣式、背景等

它處於整個json檔案的最外層,需要指定以下幾個屬性:

屬性 解釋
background 背景,可以是顏色值,也可以是圖片連結,支援本地圖片連結和網路圖片連結
width 寬度
height 高度
borderRadius 圓角
views 需要畫在圖上的其它元素,允許為空,但不允許省略

示例程式碼:

{
      background: `https://qhyxpicoss.kujiale.com/2018/06/12/LMPUSDAKAEBKKOASAAAAAAY8_981x600.png`,
      width: `654rpx`,
      height: `400rpx`,
      borderRadius: `20rpx`,
      views: []
 }
複製程式碼

view屬性

畫完了調色盤的整體屬性以後,就可以向views中增加一些元素了。元素支援四種型別,用type欄位進行區分分類。不同種類的view又要求提供有不同的資料,如image元素需要提供它的url,text元素需要提供text文字內容:

type content description 私有css屬性
image url 圖片資源地址,本地或網路
text text 文字元素,書寫文字 fontSize:字型大小,color:文字顏色
rect 矩形 color:填充顏色
qrcode content 畫二維碼 background:背景顏色,預設為透明

除了各view的私有屬性之外,view還有一些公共屬性可以設定:

屬性 作用
left, top, right, bottom 元素的位置
rotate 旋轉角度,單位為360度的度
borderRadius 圓角,如果需要設定圖片為原形,請設定該屬性為寬或高的一半
align 元素在水平方向的對齊方式,與left配合使用,可設定為left, center, right,預設為left。
rotate

控制元素的旋轉,如下圖,將一行文字順時針旋轉了6度。

{
    type: `text`,
    text: `酷家樂 移動前端`,
    css: {
     left: `20rpx`,
     top: `50rpx`,
     fontSize: `40rpx`
   },
},
複製程式碼

效果:

微信小程式朋友圈分享圖片生成方案實現

borderRadius

程式碼(圓形):

        {
          type: `image`,
          url: this.cardInfo.avatar,
          css: {
            top: `48rpx`,
            left: `448rpx`,
            width: `192rpx`,
            height: `192rpx`,
            borderRadius:`96rpx`,
          },
        },
複製程式碼

方角–>8rpx圓角–>圓形

微信小程式朋友圈分享圖片生成方案實現

align

這個屬性值比較有意思,它被用來設定元素在水平方向的、相對於位置設定的對齊方式。

什麼意思呢?

比如說你設定了某元素的left為100rpx,並設定align屬性為left,那麼該元素的左端就與100rpx對齊;若設定align為center,則該元素的中軸線與100rpx對齊。

在下面的例子中,三行文字的left都是230rpx,align分別為left, center, right。紅線是橫座標為230rpx的軸線。

即,當設定了align屬性的時候,left值表達的是元素屬性中align的位置。

微信小程式朋友圈分享圖片生成方案實現

程式碼:

		{
          type: `text`,
          text: `酷家樂 移動前端`,
          css: {
            left: `330rpx`,
            top: `100rpx`,
            fontSize: `40rpx`,
          },
        },
        {
          type: `text`,
          text: `酷家樂 移動前端`,
          css: {
            left: `330rpx`,
            top: `200rpx`,
            fontSize: `40rpx`,
            align: `center`
          },
        },
        {
          type: `text`,
          text: `酷家樂 移動前端`,
          css: {
            left: `330rpx`,
            top: `300rpx`,
            fontSize: `40rpx`,
            align: `right`
          },
        },
複製程式碼

有了這個屬性,就可以設定元素的對齊形式,完成下面的佈局要求了:

微信小程式朋友圈分享圖片生成方案實現 微信小程式朋友圈分享圖片生成方案實現

注意:align屬性請和left屬性配合使用,設定right值將造成錯誤。

align與rotate

當align屬性與rotate屬性同時存在時,元素的旋轉表現是以元素的中心點為中心的。

微信小程式朋友圈分享圖片生成方案實現

尺寸單位

目前 Painter 中支援兩種尺寸單位,px 和 rpx,代表的意思和小程式中一致。目前還沒有很好地支援百分比的使用。

儲存圖片演示

獲得圖片的url後,可以設定一個點選按鈕,點選儲存到本地

  onImgOK(e) {
    this.imagePath = e.detail.path;
  },

  saveImage() {
    wx.saveImageToPhotosAlbum({
      filePath: this.imagePath,
    })
  },
複製程式碼

按鈕繫結saveImage方法,點選進行儲存:

微信小程式朋友圈分享圖片生成方案實現

生成朋友圈分享圖

最後,利用Painter工具可以生成不同樣式的朋友圈分享圖(下圖為微信小程式 酷咖名片 線上版部分截圖)

微信小程式朋友圈分享圖片生成方案實現 微信小程式朋友圈分享圖片生成方案實現

微信小程式朋友圈分享圖片生成方案實現 微信小程式朋友圈分享圖片生成方案實現

結語

painter是酷家樂前端在小程式的實際開發中自制的一套工具,目前在朋友圈分享、皮膚模板替換等方面都在使用,覺得用起來喜憂參半。開源出來大家分享。如果它能幫助到任何一個人,我們都非常開心;我們也非常歡迎並感謝提issure或pr,來告訴我們一些我們自己沒有能想到的東西,或者幫助解決Painter 中的大大小小的坑:

再一次傳送門:github.com/Kujiale-Mob…

相關文章