在小程式中生成分享海報是一個很常見的需求,目前主要有以下兩種做法:
直接由前端生成,使用小程式提供的 canvas
API
由後端知曉雲「雲函式」生成,前端再獲取
本文將介紹通過知曉雲「雲函式」來生成分享海報的功能,並使用 webpack
和 mincloud
將程式碼打包上傳到知曉雲。
技術棧:
程式碼打包工具: webpack@4.22.0
部署工具:mincloud@1.0.4
圖片處理:gm@1.23.1
其他:知曉雲 SDK
、imageMagick
(雲函式內建)
一、專案搭建
專案檔案結構:
gm-draw-image
├── index.js
├── package.json
├── src
│ └── index.js
├── webpack.config.js
└── yarn.lock
複製程式碼
專案搭建與雲函式程式碼打包示例文件基本一致。專案搭建好後,還需要安裝以下依賴(兩種安裝方式選其一即可):
// 使用 yarn 安裝
yarn add gm mincloud
// 使用 npm 安裝
npm install --save gm mincloud
複製程式碼
修改 deploy
指令碼,如下:
// package.json
...
"scripts": {
"build": "webpack --mode production",
"predeploy": "npm run build",
"deploy": "mincloud deploy gm-draw-image ../"
},
...
複製程式碼
最終我們會使用以下兩個命令來部署和測試:
npm run deploy // 部署到知曉雲
mincloud invoke gm-draw-image // 測試已經部署到知曉雲上的雲函式
複製程式碼
二、生成海報
這裡分為 4 個步驟:
-
下載海報需要的資源
-
圖片 / 文字處理
-
海報繪製
-
將繪製完成的海報上傳到知曉雲
使用知曉雲 Node SDK 的 request
方法將資源下載下來(不能直接使用其他第三方 request
包):
BaaS.request.get(url)
.then(res => {})
.catch(err => {})
複製程式碼
引入 gm 庫對圖片進行處理,雲函式沙箱環境已經內建 `imageMagick` 工具:
const gm = require('gm').subClass({ imageMagick: true })
複製程式碼
在處理文字的時候需要注意,設定字型時需選擇知曉雲已支援的字型,詳見文件文件。
另外,這裡有一個 bug:在同一個圖層中,如果填充顏色之前有填充圖片操作,那麼後續填充的顏色將會不起作用。推薦的做法是如果有需要同時填充圖片以及填充顏色,建議將這兩個操作分開處理,最後再合成一張圖。
bug 示例如下:
gm(width, height, 'none')
.fill(bg) // 填充了一張圖片
.drawRectangle(`0, 0, ${width}, ${height}`)
.fill('#fff') // 字型顏色,這個操作不起作用
.fontSize(20)
.drawText(140, 170, 'mincloud')
複製程式碼
下載圖片,圖片儲存路徑需在 `/tmp/` 路徑下:
BaaS.request.get(url, {responseType: 'arraybuffer'})
.then(res => {})
.catch(err => {})
複製程式碼
上傳圖片到知曉雲:
var MyFile = new BaaS.File()
MyFile.upload(img, {filename: 'test.png'})
複製程式碼
完整程式碼如下:
const fs = require('fs')
const gm = require('gm').subClass({ imageMagick: true })
// 海報資源
const avatarImg = 'https://cloud-minapp-6.cloud.ifanrusercontent.com/1gQ5Mat7WAwyW1hl.jpg'
const backgroundImg = 'https://cloud-minapp-6.cloud.ifanrusercontent.com/1gQ7hCpFCK1qw8XQ.jpeg'
const MyFile = new BaaS.File()
const imageSize = {
width: 375,
height: 250,
}
function downloadImage(url) {
const filename = `/tmp/${Math.random().toString().slice(2)}.jpg`
const file = fs.createWriteStream(filename)
return BaaS.request.get(url, {responseType: 'arraybuffer'}).then(res => {
file.write(res.data)
file.end()
return filename
})
}
function uploadImage(buffer) {
return MyFile.upload(buffer, {filename: Math.random().toString().slice(2) + '.png'})
}
function drawText(filename) {
return new Promise((resolve, reject) => {
gm(imageSize.width, imageSize.height, 'none')
// 設定字型以及文字大小,這裡只能設定雲函式已支援的字型
.font('/usr/share/fonts/ttf-bitstream-vera/VeraMoBd.ttf')
.fill('#fff')
.fontSize(20)
.drawText(140, 170, 'mincloud')
.fill('#fff')
.fontSize(14)
.drawText(30, 200, 'An easy-to-use MiniApp development tool.')
.write(filename, function(err) {
if (err) {
return reject(err)
}
resolve(filename)
})
})
}
function genAvatar(avatar) {
return new Promise((resolve, reject) => {
gm(avatar)
.resize(100, 100)
.write(avatar, function(err) {
if (err) {
return reject(err)
}
resolve(avatar)
})
})
}
function genBackground(bg) {
return new Promise((resolve, reject) => {
gm(bg)
.resize(500, 350)
.blur(20, 2)
.write(bg, function(err) {
if (err) {
return reject(err)
}
resolve(bg)
})
})
}
module.exports = function (event, callback) {
const {width, height} = imageSize
const job1 = downloadImage(backgroundImg).then(res => genBackground(res))
const job2 = downloadImage(avatarImg).then(res => genAvatar(res))
const job3 = drawText('/tmp/textLayer.png')
Promise.all([job1, job2, job3]).then(res => {
gm(width, height, 'none')
.fill(res[0])
.drawRectangle(`0, 0, ${width}, ${height}`) // 繪製背景
.fill(res[1])
.drawCircle(190, 80, 190, 125) // 繪製頭像
.fill(res[2])
.drawRectangle(`0, 0, ${width}, ${height}`) // 繪製文字
.toBuffer('PNG', function (err, buffer) {
if (err) {
return callback(err)
}
uploadImage(buffer).then((res) => {
console.log('success')
callback(null, res.data.file_link)
}).catch(err => {
callback(err)
})
})
})
}
複製程式碼
三、部署並測試
跟 npm
一樣,部署前需要先登入,請參照文件配置。
使用以下命令即可將雲函式部署到知曉雲:
npm run deploy
複製程式碼
執行結果如下:
使用以下的命令來測試:
mincloud invoke image-crawler
複製程式碼
執行結果如下:
上傳到知曉雲的圖片如下:
生成的海報效果圖:
素材原圖:
四、參考文件
知曉雲開發文件:doc.minapp.com/
gm 官方文件:aheckmann.github.io/gm/docs.htm…