日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

微信小程序之生成图片保存到相册

發布時間:2025/3/21 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 微信小程序之生成图片保存到相册 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

微信小程序之生成圖片保存到相冊

需求概要

電商項目中需要將自己小店的商品帶上自己的小程序碼生成海報,保存到本地,然后分享到萬能的朋友圈,QQ空間,微博等等來廣而告之…
如下圖,三種海報格式輪播展示,左滑右滑切換到海報,點擊下面保存圖片按鈕,將當前海報保存到手機相冊

思路

1、需要商品信息,用戶信息以及小程序碼。

2、使用swiper組件展示海報,

3、將海報通過wx.createCanvasContext繪制到畫布canvas組件。

4、使用canvasToTempFilePath 將canvas海報保存到本地臨時文件路徑;

5、使用saveImageToPhotosAlbum將圖片保存到本地相冊

6、根據swiper組件的current屬性判斷當前保存的海報

解決方案

按照思路逐步實現:

商品信息,用戶信息以及小程序碼

1.商品信息通過導航事件傳遞到海報頁,在此我使用的是模擬數據;

2.用戶信息通過本地存儲wx.setStorageSync 到緩存。

// index.js//事件處理函數navToShare: function () {// 模擬數據var data = {thumb_images: ['https://cbu01.alicdn.com/img/ibank/2018/544/692/8567296445_882293189.400x400.jpg','https://cbu01.alicdn.com/img/ibank/2018/971/643/8581346179_882293189.400x400.jpg','https://cbu01.alicdn.com/img/ibank/2018/184/392/8567293481_882293189.400x400.jpg'],name: '2018夏季新款鏤空圓領蝙蝠短袖t恤女裝韓版寬松棉小衫上衣批發潮',price: 198,}wx.navigateTo({url: '../poster/poster?data=' + encodeURIComponent(JSON.stringify(data))})},

3.在海報頁面onLoad函數的參數中獲取商品信息

4.在海報頁面獲取本地緩存中的用戶信息wx.getStorageSync

5.因為canvas繪制圖片不支持跨域圖片,所以先使用getImageInfo將網絡圖片返回圖片的本地路徑,

// poster.jsonLoad: function(options) {var data = JSON.parse(decodeURIComponent(options.data));var userinfo;// 獲取本地存儲的用戶頭像和昵稱 userinfo = wx.getStorageSync('userInfo');console.log('用戶信息', userinfo)// 渲染頁面this.setData({avatar_url: userinfo.avatarUrl,nickname: userinfo.nickName,thumb_images: data.thumb_images,pro_price: data.price,pro_name: data.name,})// 保存網絡圖片到本地 用于canvas繪制圖片wx.getImageInfo({src: userinfo.avatarUrl,success: (res) => {tmpAvatarUrl = res.path;}});// 保存產品圖到本地 用于canvas繪制圖片var thumbs = data.thumb_images;tmpThumbs = []; // 先清空,再添加新的產品圖thumbs.forEach((item, i) => {wx.getImageInfo({src: item,success: (res) => {tmpThumbs.push(res.path)}})});},

6.小程序碼由后端生成,前端通過POST請求將data傳入,返回小程序碼url,使用 wx.getImageInfo保存到本地

// 封裝后的POST方法 wxRequest.postRequest(url, data).then(res => {if (res.data.error_code == 0) {// 保存小程序碼到本地 用于canvas繪制圖片wx.getImageInfo({src: res.data.qrcode,success: (result) => {this.setData({poster_qrcode: result.path})}});} })

使用swiper組件展示海報

在這個項目中我是將頁面渲染和canvas繪制分開的,因為小程序單位rpx自動適配各種設備屏幕。而canvas繪制單位是px。我沒有做px和rpx之間的計算,保存px單位固定大小的圖片也不錯。

<view class='poster_swiper'><swiper bindchange="shareChange" current="{{current}}" circular="{{circular}}" previous-margin="100rpx" next-margin="100rpx" class="swiper_share"><swiper-item class="swiper_item1">// 根據設計渲染頁面</swiper-item><swiper-item class="swiper_item2" wx:if="{{thumb_images.length>1}}">// 根據設計渲染頁面</swiper-item><swiper-item class="swiper_item3" wx:if="{{thumb_images.length>2}}">// 根據設計渲染頁面</swiper-item></swiper> </view>

這里要用到swiper的幾個屬性列出來

將海報通過wx.createCanvasContext繪制到畫布canvas組件。。

1.在wxml中添加canvas組件,設置canvas-id以便于wx.createCanvasContext繪制畫布

<canvas class='canvas-poster' canvas-id='canvasposter'></canvas>

定義樣式固定定位到可視區以外,不影響可視區展示。

.canvas-poster {position: fixed;width: 280px;height: 450px;top: 100%;left: 100%;overflow: hidden; }

三種海報分別繪制,具體看注釋

/*一張產品圖*/drawPosterOne: function() {var ctx = wx.createCanvasContext('canvasposter');// ctx.clearRect(0, 0, 280, 450);/* 繪制背景*/ctx.rect(0, 0, 280, 450);ctx.setFillStyle('white');ctx.fillRect(0, 0, 280, 450);/*繪制店名*/ctx.setFontSize(16);ctx.setFillStyle('#333');ctx.textAlign = "center";ctx.fillText(this.data.nickname + '的小店', 140, 70);ctx.restore();/*繪制產品圖*/ctx.drawImage(tmpThumbs[0], 35, 90, 210, 210);/* 繪制產品名稱背景*/ctx.setFillStyle('#FF8409');ctx.fillRect(35, 300, 210, 60);/*繪制產品名稱*/ctx.setFontSize(12);ctx.setFillStyle('#ffffff');ctx.textAlign = "left";ctx.fillText(this.data.pro_name.substr(0, 18), 45, 322);ctx.restore();ctx.setFontSize(12);ctx.setFillStyle('#ffffff');ctx.textAlign = "left";ctx.fillText(this.data.pro_name.substr(18, 20), 45, 344);ctx.restore();/* 繪制線框*/ctx.setLineDash([1, 3], 1);ctx.beginPath();ctx.moveTo(35, 375);ctx.lineTo(160, 375);ctx.moveTo(35, 435);ctx.lineTo(160, 435);ctx.setStrokeStyle('#979797');ctx.stroke();ctx.restore();/*繪制文字*/ctx.setFontSize(14);ctx.setFillStyle('#333333');ctx.textAlign = "left";ctx.fillText('¥', 35, 400);ctx.setFontSize(18);ctx.fillText(this.data.pro_price, 50, 400);ctx.setFontSize(11);ctx.setFillStyle('#666666');ctx.fillText(this.data.poster_qrtext, 35, 420);ctx.restore();/*繪制二維碼*/ctx.drawImage(this.data.poster_qrcode, 185, 370, 60, 60);ctx.restore();/*圓形頭像*/ctx.save()ctx.beginPath();ctx.arc(140, 30, 20, 0, 2 * Math.PI)ctx.setFillStyle('#fff')ctx.fill()ctx.clip()ctx.drawImage(tmpAvatarUrl, 120, 10, 40, 40)ctx.restore()ctx.draw(false, this.getTempFilePath);},/*兩張產品圖*/drawPosterTwo: function() {var ctx = wx.createCanvasContext('canvasposter');/* 繪制背景*/ctx.rect(0, 0, 280, 450);ctx.setFillStyle('white');ctx.fillRect(0, 0, 280, 450);/*繪制店名*/ctx.setFontSize(14);ctx.setFillStyle('#333');ctx.textAlign = "left";ctx.fillText(this.data.nickname + '的小店', 65, 36);ctx.restore();/* 繪制虛線框*/ctx.setLineDash([4, 1], 1);ctx.beginPath();ctx.moveTo(25, 60);ctx.lineTo(255, 60);ctx.moveTo(25, 325);ctx.lineTo(255, 325);ctx.setStrokeStyle('#979797');ctx.stroke();ctx.restore();/*繪制產品名稱*/ctx.setFontSize(12);ctx.setFillStyle('#333');ctx.textAlign = "left";ctx.fillText(this.data.pro_name.substr(0, 13), 25, 82);ctx.setFontSize(12);ctx.setFillStyle('#333');ctx.fillText(this.data.pro_name.substr(13, 12) + '...', 25, 100);ctx.restore();/*繪制文字*/ctx.setFontSize(14);ctx.setFillStyle('#333333');ctx.textAlign = "left";ctx.fillText('¥', 190, 90);ctx.setFontSize(16);ctx.fillText(this.data.pro_price, 205, 90);ctx.restore();ctx.setFontSize(10);ctx.setFillStyle('#666666');ctx.textAlign = "center";ctx.fillText(this.data.poster_qrtext, 140, 420);ctx.restore();/*繪制產品圖*/ctx.drawImage(tmpThumbs[0], 25, 115, 110, 150);ctx.drawImage(tmpThumbs[1], 145, 115, 110, 150);ctx.restore();/*繪制文字*/ctx.setFontSize(12);ctx.setFillStyle('#333333');ctx.textAlign = "left";ctx.fillText(this.data.slogan1, 25, 290);ctx.fillText(this.data.slogan2, 25, 308);ctx.restore();/*繪制二維碼*/ctx.drawImage(this.data.poster_qrcode, 110, 330, 70, 70);ctx.restore();/*圓形頭像*/ctx.save()ctx.beginPath();ctx.arc(35, 30, 20, 0, 2 * Math.PI)ctx.setFillStyle('#fff')ctx.fill()ctx.clip()ctx.drawImage(tmpAvatarUrl, 15, 10, 40, 40)ctx.restore()ctx.draw(false, this.getTempFilePath);},/*三張產品圖*/drawPosterThree: function() {var ctx = wx.createCanvasContext('canvasposter');/* 繪制背景*/ctx.rect(0, 0, 280, 450);ctx.setFillStyle('white');ctx.fillRect(0, 0, 280, 450);/*繪制店名*/ctx.setFontSize(16);ctx.setFillStyle('#333');ctx.textAlign = "center";ctx.fillText(this.data.nickname + '的小店', 140, 70);ctx.restore();/* 繪制虛線框*/ctx.beginPath()ctx.setLineDash([4, 1], 1);ctx.beginPath();ctx.moveTo(20, 230);ctx.lineTo(145, 230);ctx.lineTo(145, 305);ctx.lineTo(40, 305);/*左下角圓角 ctx.arcTo( , 左下角左邊坐標,左上角左邊坐標,半徑)*/ctx.arcTo(20, 305, 20, 230, 20);ctx.moveTo(20, 230);ctx.lineTo(20, 285);ctx.setStrokeStyle('#333333')ctx.stroke()ctx.setStrokeStyle('#979797');ctx.stroke();ctx.restore();/*繪制產品名稱*/ctx.setFontSize(12);ctx.setFillStyle('#333');ctx.textAlign = "left";ctx.fillText(this.data.pro_name.substr(0, 9), 30, 250);ctx.setFontSize(12);ctx.setFillStyle('#333');ctx.fillText(this.data.pro_name.substr(9, 8) + '...', 30, 268);ctx.restore();/*繪制文字*/ctx.setFontSize(14);ctx.setFillStyle('#333333');ctx.textAlign = "left";ctx.fillText('¥', 30, 290);ctx.setFontSize(16);ctx.fillText(this.data.pro_price, 45, 290);ctx.restore();ctx.setFontSize(10);ctx.setFillStyle('#666666');ctx.textAlign = "center";ctx.fillText(this.data.poster_qrtext, 140, 420);ctx.restore();/*繪制產品圖*/ctx.drawImage(tmpThumbs[0], 20, 90, 125, 125);ctx.drawImage(tmpThumbs[1], 160, 90, 100, 100);ctx.drawImage(tmpThumbs[2], 160, 205, 100, 100);ctx.restore();ctx.restore();/*繪制二維碼*/ctx.drawImage(this.data.poster_qrcode, 110, 330, 70, 70);ctx.restore();/*圓形頭像*/ctx.save()ctx.beginPath();ctx.arc(140, 30, 20, 0, 2 * Math.PI)ctx.setFillStyle('#fff')ctx.fill()ctx.clip()ctx.drawImage(tmpAvatarUrl, 120, 10, 40, 40)ctx.restore()ctx.draw(false, this.getTempFilePath);},

繪制中用到的數據如下

var tmpAvatarUrl = ""; /*用于繪制頭像*/ var tmpThumbs = []; /*用于繪制產品圖*/ var drawing = false; /*避免多次點擊保存按鈕*/ Page({/*** 頁面的初始數據*/data: {circular: true, // swiper 是否采用銜接滑動current: 0, // swiper 當前所在滑塊的 indexavatar_url: '', // 渲染頭像nickname: '', // 渲染昵稱poster_qrcode: '/images/poster_qrcode.png', // 小程序碼poster_qrtext: '長按識別,即可查看商品',pro_name: '', //產品名pro_price: '', // 產品價格slogan1: '我的小店上新了,', // 標語 1slogan2: '快來一起快來一起看看吧!', // 標語 2thumb_images: [] // 渲染圖片},

使用canvasToTempFilePath 將canvas海報保存到本地臨時文件路徑;

//獲取臨時路徑getTempFilePath: function() {wx.canvasToTempFilePath({canvasId: 'canvasposter',success: (res) => {this.saveImageToPhotosAlbum(res.tempFilePath)}})},

使用saveImageToPhotosAlbum將圖片保存到本地相冊

//保存至相冊saveImageToPhotosAlbum: function(imgUrl) {if (imgUrl) {wx.saveImageToPhotosAlbum({filePath: imgUrl,success: (res) => {wx.showToast({title: '保存成功',icon: 'success',duration: 2000})drawing = false},fail: (err) => {wx.showToast({title: '保存失敗',icon: 'none',duration: 2000})drawing = false}})}else{wx.showToast({title: '繪制中……',icon: 'loading',duration: 3000})}},

注意canvas繪制需要時間,所以設置 drawing 防止繪制被打斷

根據swiper組件的current屬性判斷當前保存的海報

1.首先根據 change 事件設置current

shareChange: function(e) {if (e.detail.source == 'touch') {this.setData({current: e.detail.current})}},

2.通過點擊按鈕執行savePoster保存海報到手機相冊

<view class="common_btn" catchtap="savePoster"><text>保存圖片</text></view>

判斷是否獲取相冊授權,已獲得權限直接繪制,若未獲得權限需提示用戶前去設置授權

/*保存海報到手機相冊*/savePoster: function(e) {var that = this;var current = this.data.current;//獲取相冊授權wx.getSetting({success(res) {if (!res.authSetting['scope.writePhotosAlbum']) {wx.authorize({scope: 'scope.writePhotosAlbum',success() { //這里是用戶同意授權后的回調that.drawPoster(current);},fail() { //這里是用戶拒絕授權后的回調wx.showModal({title: '提示',content: '若不打開授權,則無法將圖片保存在相冊中!',showCancel: true,cancelText: '去授權',cancelColor: '#000000',confirmText: '暫不授權',confirmColor: '#3CC51F',success: function(res) {if (res) {wx.openSetting({//調起客戶端小程序設置界面,返回用戶設置的操作結果。})} else {// console.log('用戶點擊取消')}}})}})} else { //用戶已經授權過了 that.drawPoster(current);}}})},

3.根據current判斷當前海報繪制對應海報

/* 繪制海報*/drawPoster: function(current) {if(drawing){wx.showToast({title: '繪制中……',icon: 'loading',duration: 3000}) }else{drawing = true;// loading // 根據swiper當前所在滑塊的 index判斷繪制對應海報switch (current) {case 0:this.drawPosterOne()break;case 1:this.drawPosterTwo()break;case 2:this.drawPosterThree()break;}}},

保存到手機相冊的海報如下:

總結

以上是生活随笔為你收集整理的微信小程序之生成图片保存到相册的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 91老师片黄在线观看 | 一道本av在线 | 成人在线观看a | 国精无码欧精品亚洲一区蜜桃 | 亚洲中文一区二区三区 | fc2ppv在线播放| 依人综合网 | 欧美又大粗又爽又黄大片视频 | 日韩av三区| 四虎新网址 | 理论毛片| 伊人久久久久噜噜噜亚洲熟女综合 | 日韩福利在线观看 | 91视频网页 | 免费性片| 热热久 | 久久久久久国产精品免费 | 欧美一级片播放 | 99久久人妻无码精品系列 | 爱情岛论坛自拍亚洲品质极速最新章 | 清清草免费视频 | 成人污污视频在线观看 | 师生出轨h灌满了1v1 | 中文字幕在线播放av | 操你啦影院 | 极品尤物魔鬼身材啪啪仙踪林 | 刘亦菲毛片一区二区三区 | 麻豆精品免费视频 | 国产精品av在线播放 | 成人在线综合网 | 大尺度在线观看 | 日韩欧美国产三级 | 成人极品视频 | xxxx黄色| 原神女裸体看个够无遮挡 | 国产美女在线看 | 亚洲第一激情 | 国产精品精品视频 | 97av在线 | 揉我啊嗯~喷水了h视频 | 好吊视频一区二区三区 | 91原创视频在线观看 | 网友自拍视频 | 美女精品在线 | 国产精品国产三级国产专播品爱网 | 99久久久无码国产精品不卡 | 亚洲国产精华液网站w | 一级黄色性生活片 | 成人免费看类便视频 | 欧美狠狠 | 国产成人精品电影 | 亚洲 成人 av| 国产伦精品一区二区三区网站 | 97精品国产97久久久久久粉红 | 日韩乱码人妻无码中文字幕 | 打屁屁日本xxxxx变态 | 婷婷五月情| 欧美做受喷浆在线观看 | 成人黄色免费网址 | 欧美男人又粗又长又大 | 亚洲欧美精品在线观看 | 国产又大又长又粗 | 97人人澡人人爽人人模亚洲 | 国产精品探花在线观看 | 中文字幕乱视频 | 日韩高清成人 | 久热免费在线视频 | 人妻激情偷乱频一区二区三区 | 男女啪动最猛动态图 | 亚洲AV无码国产精品国产剧情 | 18做爰免费视频网站 | 少妇在线视频 | 69国产 | 黄色一机片 | 韩毛片 | 少妇不卡视频 | 狠狠久久综合 | 精品国产一二三区 | 日韩成人精品在线 | 国产无遮挡又黄又爽又色 | 亚洲制服丝袜av | 日日碰日日摸 | 啪啪网站视频 | 午夜视频观看 | 日韩精品福利视频 | 免费黄网在线观看 | 国产99久久九九精品无码免费 | 熟女熟妇伦久久影院毛片一区二区 | 久久男女视频 | 日日爽天天 | 国产中文字字幕乱码无限 | 天堂av2019| 亚洲激情一区 | 青青草手机视频在线观看 | 波多野结衣调教 | 黄色资源在线 | 中文精品久久久久人妻不卡 | 在线无码va中文字幕无码 | 日本一区二区三区免费看 |