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

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

因此咱們準備了一套名爲Painter的工具, 爲開發者提供一種簡單實用的「繪製」圖片的解決思路,讓開發者能夠自由地生成本身想要的圖片文件。前端

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

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

canvas的坑

painter從實現上來說,是用了小程序的canvas做爲載體來實現以上功能的。而canvas有不少著名的坑。有的坑,咱們當心翼翼地繞了過去;有的坑,咱們仍是痛快淋漓地一腳踩了下去……github

  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的功能

如圖所示shell

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

Painter閱讀完代碼,繪製成圖片之後,會將圖片的連接返回給咱們。此時,咱們能夠將圖片上傳、保存到本地或者顯示在屏幕上。canvas

它能夠很方便地定製所須要的圖片,還能夠自由動態地給圖片更換風格。小程序

此外,小程序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…

相關文章
相關標籤/搜索