小程序 生成自定義小程序二維碼碼 通過(guò) canvas 生成海報(bào) 保存成圖片

功能很簡(jiǎn)單 但是有坑

廢話不多說(shuō)直接上代碼

html

canvas 定義畫(huà)板 構(gòu)造海報(bào)? .preview 生成海報(bào)圖瀏覽 模板框?

<canvas canvas-id="shareImg" class="canvas-exp"></canvas>

<view hidden='{{previewHidden}}' class='preview'>

? <image src='{{preurl}}' mode='widthFix' class='previewImg'></image>

? <button type='primary' bindtap='save' style="background:#0A655A">保存到本地</button>

</view>

<button class='shares' type='primary' bindtap='share'>生成成績(jī)單</button>

css

.shares{

? position: absolute;

? bottom: 100rpx;

? width: 70%;

? left: 15%;

? height: 100rpx;

? line-height: 100rpx;

}

.canvas-exp{

? width:100%;height:606px;background:#fff;

}

.preview {

? width: 100%;

? height: 100%;

? background: rgba(0,0,0,1);

? position:fixed;

? top: 0;

? left: 0;

? z-index: 2;

}

.previewImg{

? width: 88%;

? position: absolute;

? top: 100rpx;

? left: 6%;

? z-index: 3;

? border: 1px solid #000;

? border-radius: 5px;

? max-height: 800rpx;

}

.preview button{

? width: 78%;

? position: absolute;

? top: 960rpx;

? left: 11%;

? border-radius: 2px;

}

.preview .cler{

? width: 64rpx;

? height: 64rpx;

? position: absolute;

? top: 1100rpx;

? left: 50%;

? margin-left: -32rpx;

}

核心代碼 js

// pages/all/index.js

Page({

? /**

? * 頁(yè)面的初始數(shù)據(jù)

? */

? data: {

? ? currentLineHeight: 0,

? ? previewHidden: true

? },

? onLoad(){

? ? this.createCanvasContext()

? },

? createCanvasContext() {

? ? let that =this

? ? var expiration = wx.getStorageSync("index_data_expiration"); //拿到過(guò)期時(shí)間

? ? var timestamp = Date.parse(new Date()); //拿到現(xiàn)在時(shí)間

? ? // access_token 過(guò)期時(shí)間

? ? if (wx.getStorageSync('access_token') && expiration > timestamp) {

? ? ? console.log(wx.getStorageSync('access_token'))

? ? ? that.accessToken(wx.getStorageSync('access_token'))

? ? } else {

? ? ? wx.request({

? ? ? ? url: 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=appid&secret=secret',

? ? ? ? method: 'get',

? ? ? ? success: function (ress) {

? ? ? ? ? wx.setStorageSync("access_token", ress.data.access_token)

? ? ? ? ? var timestamp = Date.parse(new Date());

? ? ? ? ? var expiration = timestamp + ress.data.expires_in

? ? ? ? ? console.log(ress.data.access_token)

? ? ? ? ? wx.setStorageSync("expires_in", expiration)

? ? ? ? ? that.accessToken(ress.data.access_token)

? ? ? ? },

? ? ? ? fail: function (res) {

? ? ? ? ? console.log(res)

? ? ? ? }

? ? ? })

? ? }

? },

? accessToken(access_token) {

? ? let that = this

? ? let winWidth = wx.getSystemInfoSync().windowWidth; // 獲取當(dāng)前設(shè)備的可視寬度

? ? let winHeight = wx.getSystemInfoSync().windowHeight; // 獲取當(dāng)前設(shè)備的可視高度

? ? that.setData({

? ? ? winWidth: winWidth,

? ? ? winHeight: winHeight

? ? })

? ? let data = {

? ? ? page: 'pages/hotinfo/hotinfo',

? ? ? scene: '12'

? ? }

? ? wx.request({

? ? ? url: 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' + access_token,

? ? ? method: 'POST',

? ? ? data: data,

? ? ? // dataType: 'json',

? ? ? responseType: 'arraybuffer', //將返回?cái)?shù)據(jù) 按文本解析修改為arraybuffer

? ? ? success: function (res) {

? ? ? ? console.log(res)


? ? ? ? // 利用writeFile bese64圖片存本地文件使用

? ? ? ? var imgPath = wx.env.USER_DATA_PATH + '/tabhome' + 'ewm' + '.png';

? ? ? ? var fs = wx.getFileSystemManager();

? ? ? ? fs.writeFileSync(imgPath, res.data, "base64");


? ? ? ? ? const ctx = wx.createCanvasContext('shareImg')

? ? ? ? ? var Rpx = (winWidth / 375).toFixed(2);


? ? ? ? ? ctx.setFillStyle('#fff')

? ? ? ? ? ctx.fillRect(0, 0, winWidth, 800)

? ? ? ? ? ctx.drawImage('../../' + res[0].path, 0, 0, winWidth, 228 * Rpx)

? ? ? ? ? var currentLineHeight = 228 * Rpx + 10;

? ? ? ? ? ctx.setTextAlign('left')

? ? ? ? ? ctx.setFillStyle('#2E2F2F')

? ? ? ? ? ctx.setTextAlign('left')

? ? ? ? ? let contentTitle = '這世界,來(lái)過(guò),愛(ài)過(guò),奮斗過(guò),何懼解決如何---悟空!這世界,來(lái)過(guò),愛(ài)過(guò),奮斗過(guò),何懼解決如何---悟空!'

? ? ? ? ? var chr = contentTitle.split(""); //這個(gè)方法是將一個(gè)字符串分割成字符串?dāng)?shù)組

? ? ? ? ? var temp = "";

? ? ? ? ? var row = [];

? ? ? ? ? for (var a = 0; a < chr.length; a++) {

? ? ? ? ? ? if (ctx.measureText(temp).width < winWidth / 2 - 10) {

? ? ? ? ? ? ? temp += chr[a];

? ? ? ? ? ? } else {

? ? ? ? ? ? ? a--;

? ? ? ? ? ? ? row.push(temp);

? ? ? ? ? ? ? temp = "";

? ? ? ? ? ? }

? ? ? ? ? }

? ? ? ? ? row.push(temp);

? ? ? ? ? //如果數(shù)組長(zhǎng)度大于2 則截取前兩個(gè)

? ? ? ? ? if (row.length > 2) {

? ? ? ? ? ? var rowCut = row.slice(0, 2);

? ? ? ? ? ? var rowPart = rowCut[1];

? ? ? ? ? ? var test = "";

? ? ? ? ? ? var empty = [];

? ? ? ? ? ? for (var a = 0; a < rowPart.length; a++) {

? ? ? ? ? ? ? if (ctx.measureText(test).width < winWidth / 2 - 10) {

? ? ? ? ? ? ? ? test += rowPart[a];

? ? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? empty.push(test);

? ? ? ? ? ? var group = empty[0] + "..." //這里只顯示兩行,超出的用...表示

? ? ? ? ? ? rowCut.splice(1, 1, group);

? ? ? ? ? ? row = rowCut;

? ? ? ? ? }

? ? ? ? ? ctx.font = 'normal bold 18px sans-serif';

? ? ? ? ? for (var b = 0; b < row.length; b++) {

? ? ? ? ? ? currentLineHeight += Rpx * 30;

? ? ? ? ? ? ctx.fillText(row[b], 15, currentLineHeight);

? ? ? ? ? }

? ? ? ? ? currentLineHeight += 80 * Rpx

? ? ? ? ? ctx.drawImage('../../' + 'assets/coupon_gold.png', 20, currentLineHeight, 60 * Rpx, 60 * Rpx)

? ? ? ? ? currentLineHeight += 35 * Rpx

? ? ? ? ? ctx.fillText('健健康康', 90 * Rpx, currentLineHeight);

? ? ? ? ? ctx.drawImage(imgPath, winWidth - 120 * Rpx, currentLineHeight - 70, 100 * Rpx, 100 * Rpx)

? ? ? ? ? currentLineHeight += 100 - 40 * Rpx

? ? ? ? ? ctx.stroke()

? ? ? ? ? ctx.draw()

? ? ? ? ? that.setData({

? ? ? ? ? ? currentLineHeight: currentLineHeight

? ? ? ? ? })

? ? ? ? })

? ? ? }

? },

? save: function () {

? ? var that = this;

? ? //獲取相冊(cè)授權(quán)

? ? wx.getSetting({

? ? ? success(res) {

? ? ? ? if (!res.authSetting['scope.writePhotosAlbum']) {

? ? ? ? ? wx.authorize({

? ? ? ? ? ? scope: 'scope.writePhotosAlbum',

? ? ? ? ? ? success() {

? ? ? ? ? ? ? that.savaImageToPhoto();

? ? ? ? ? ? }

? ? ? ? ? })

? ? ? ? } else {

? ? ? ? ? that.savaImageToPhoto();

? ? ? ? }

? ? ? }

? ? })

? },

? /**

? * 生成分享圖

? */

? share: function () {

? ? var that = this

? ? wx.showLoading({

? ? ? title: '努力生成中...'

? ? })

? ? wx.canvasToTempFilePath({

? ? ? x: 0,

? ? ? y: 0,

? ? ? width: this.data.winWidth,

? ? ? height: this.data.currentLineHeight,

? ? ? destWidth: this.data.winWidth,

? ? ? destHeight: this.data.currentLineHeight,

? ? ? canvasId: 'shareImg',

? ? ? success: function (res) {

? ? ? ? console.log(res.tempFilePath);

? ? ? ? that.setData({

? ? ? ? ? preurl: res.tempFilePath,

? ? ? ? ? previewHidden: false,

? ? ? ? })

? ? ? ? wx.hideLoading()

? ? ? },

? ? ? fail: function (res) {

? ? ? ? console.log(res)

? ? ? }

? ? })

? },

? savaImageToPhoto: function () {

? ? let that = this;

? ? wx.showLoading({

? ? ? title: '努力生成中...'

? ? })

? ? wx.canvasToTempFilePath({

? ? ? x: 0,

? ? ? y: 0,

? ? ? width: that.data.winWidth,

? ? ? height: that.data.winHeight - 70,

? ? ? destWidth: that.data.winWidth,

? ? ? destHeight: that.data.winHeight - 70,

? ? ? canvasId: 'shareImg',

? ? ? success: function (res) {

? ? ? ? console.log(res)

? ? ? ? wx.hideLoading()

? ? ? ? wx.saveImageToPhotosAlbum({

? ? ? ? ? filePath: res.tempFilePath,

? ? ? ? ? success(res) {

? ? ? ? ? ? wx.showModal({

? ? ? ? ? ? ? content: '圖片已保存到相冊(cè)',

? ? ? ? ? ? ? showCancel: false,

? ? ? ? ? ? ? confirmText: '知道啦',

? ? ? ? ? ? ? confirmColor: '#72B9C3',

? ? ? ? ? ? ? success: function (res) {

? ? ? ? ? ? ? ? if (res.confirm) {

? ? ? ? ? ? ? ? ? console.log('用戶點(diǎn)擊確定');

? ? ? ? ? ? ? ? ? that.setData({

? ? ? ? ? ? ? ? ? ? hidden: true

? ? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? }

? ? ? ? ? ? })

? ? ? ? ? }

? ? ? ? })

? ? ? },

? ? ? fail: function (res) {

? ? ? ? console.log(res)

? ? ? }

? ? })

? },

})

https://api.weixin.qq.com只能用后端請(qǐng)求獲取 前端只可供體驗(yàn)參考 不然線上會(huì)出問(wèn)題

1.通過(guò)小程序api 接口?https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=appid&secret=secret? (get)

獲取 token值? 時(shí)效兩個(gè)小時(shí)?

2.再通過(guò)api 接口?https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=access_token 獲取自定義參數(shù)的小程序碼?(POST)

01.scene 為要攜帶的參數(shù) 最高32位? ?具體看小程序api文檔? 接口返回的格式為?arraybuffer

02.請(qǐng)求是注意? 參數(shù)修改??responseType: 'arraybuffer', //將返回?cái)?shù)據(jù) 按文本解析修改為arraybuffer

03.通過(guò)api?wx.arrayBufferToBase64() 將數(shù)據(jù)轉(zhuǎn)為bese64? ?例:

let URL ='data:image/png;base64,' + wx.arrayBufferToBase64(res.data)

04.小程序canvas bese64圖片 模擬器可正常顯示?真機(jī)操作則無(wú)效? 因canvas圖片不支持base64?

處理方法為利用writeFile bese64圖片存本地文件使用 例:

var imgPath = wx.env.USER_DATA_PATH + '/tabhome' + 'ewm' + '.png';

var fs = wx.getFileSystemManager();

fs.writeFileSync(imgPath, res.data, "base64");

wx.env.USER_DATA_PATH 為微信提供無(wú)需在意? ?'/tabhome' 為本頁(yè)面路徑?ewm為自定義

writeFileSync內(nèi)的imgPath為自定義的文件路徑 (本地路徑)?

writeFileSync內(nèi)的res.data 為獲取到的arraybuffer值?

writeFileSync內(nèi)的base64 為數(shù)據(jù)類型

imgPath拿到的 就是本地的圖片路徑 可直接使用到項(xiàng)目中

3.利用wx.createCanvasContext創(chuàng)建畫(huà)板 進(jìn)行繪畫(huà)?文字太多 自動(dòng)換行兩行省略處理 圖片路徑一定要正確 不然只會(huì)看到空白的canvas

4.利用wx.canvasToTempFilePath() 將canvas截取生成圖片? 區(qū)域可自定義 具體請(qǐng)看官方文檔

5.wx.saveImageToPhotosAlbum? 保存圖片到手機(jī)相冊(cè)

流程:

通過(guò)canvas提前繪制海報(bào)

再通過(guò)wx.canvasToTempFilePath() 截取繪制好的海報(bào)

最后通過(guò)wx.saveImageToPhotosAlbum? 保存圖片到手機(jī)相冊(cè)

這樣就大功告成了


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容