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

功能很簡單 但是有坑

廢話不多說直接上代碼

html

canvas 定義畫板 構(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'>生成成績單</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({

? /**

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

? */

? data: {

? ? currentLineHeight: 0,

? ? previewHidden: true

? },

? onLoad(){

? ? this.createCanvasContext()

? },

? createCanvasContext() {

? ? let that =this

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

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

? ? // access_token 過期時(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 = '這世界,來過辐烂,愛過郑藏,奮斗過闸氮,何懼解決如何---悟空鹅心!這世界猎塞,來過垢乙,愛過渣慕,奮斗過,何懼解決如何---悟空裂逐!'

? ? ? ? ? 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ù)組長度大于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ì)出問題

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

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

2.再通過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.通過api?wx.arrayBufferToBase64() 將數(shù)據(jù)轉(zhuǎn)為bese64? ?例:

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

04.小程序canvas bese64圖片 模擬器可正常顯示?真機(jī)操作則無效? 因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 為微信提供無需在意? ?'/tabhome' 為本頁面路徑?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)建畫板 進(jìn)行繪畫?文字太多 自動(dòng)換行兩行省略處理 圖片路徑一定要正確 不然只會(huì)看到空白的canvas

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

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

流程:

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

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

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

這樣就大功告成了


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市卜高,隨后出現(xiàn)的幾起案子弥姻,更是在濱河造成了極大的恐慌,老刑警劉巖掺涛,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庭敦,死亡現(xiàn)場離奇詭異,居然都是意外死亡鸽照,警方通過查閱死者的電腦和手機(jī)螺捐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人定血,你說我怎么就攤上這事赔癌。” “怎么了澜沟?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵灾票,是天一觀的道長。 經(jīng)常有香客問我茫虽,道長刊苍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任濒析,我火速辦了婚禮正什,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘号杏。我一直安慰自己婴氮,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布盾致。 她就那樣靜靜地躺著主经,像睡著了一般。 火紅的嫁衣襯著肌膚如雪庭惜。 梳的紋絲不亂的頭發(fā)上罩驻,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天,我揣著相機(jī)與錄音护赊,去河邊找鬼惠遏。 笑死,一個(gè)胖子當(dāng)著我的面吹牛百揭,可吹牛的內(nèi)容都是我干的爽哎。 我是一名探鬼主播蜓席,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼器一,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了厨内?” 一聲冷哼從身側(cè)響起祈秕,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎雏胃,沒想到半個(gè)月后请毛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瞭亮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年方仿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡仙蚜,死狀恐怖此洲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情委粉,我是刑警寧澤呜师,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站贾节,受9級(jí)特大地震影響汁汗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜栗涂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一知牌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧斤程,春花似錦送爸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至球匕,卻和暖如春纹磺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背亮曹。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來泰國打工橄杨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人照卦。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓式矫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親役耕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子采转,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353