生成画报并保存到本地
在做小程序项目的时候有一个功能是保存商品图片和商品对应的二维码信息并生成多张画报图片并保存。来记录一下实现的方式。
1.效果图
2.分析一下这个功能如何实现
查看了小程序API之后,得出结论这个功能只能通过在canvas上绘制图片和文字来实现。参考微信公众平台api获取CanvasContext:wx.createCanvasContext,canvas操作:CanvasContext操作
3.实现代码
index.js
Page({
/**
* 页面的初始数据
*/
data: {
scan: '长按识别二维码',
proNo: '款号:AAAA',
imageWidth:300,
imageHeight:450,
codeUrl:'https://code.jpg',
picList:['http://p1.png','https://p2.png'],
price:'价格:¥999',
downloadCount:0
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
wx.setNavigationBarTitle({
title: '下载图片',
})
this.setData({
picList:piclist,
codeUrl:codeDownload,
proNo:no,
price:price
})
this.downLoadCodePic()
},
downLoadCodePic: function(){
var that = this
let codeUrl = that.data.codeUrl
wx.showLoading({
title: '下载中',
})
wx.downloadFile({
url: codeUrl,
success(res){
if(res.statusCode == 200){
that.setData({
codeUrl:res.tempFilePath
})
that.downloadTempPic()
}
}
})
},
/**
* 下载资源文件
*/
downloadTempPic: function(){
var that = this
var piclist = this.data.picList
var tempPaths =[]
for(var i = 0;i < piclist.length;i++){
var url = piclist[i]
wx.downloadFile({
url: url,
success (res) {
console.log(res)
// 只要服务器有响应数据,就会把响应内容写入文件并进入 success 回调,业务需要自行判断是否下载到了想要的内容
if (res.statusCode === 200) {
var tempPath = res.tempFilePath
tempPaths.push(tempPath)
//下载完成
if(tempPaths.length == piclist.length){
for (var i = 0; i < tempPaths.length; i++) {
let canvasId = 'canvas' + i
that.createNewImg(tempPaths[i], canvasId)
that.saveimg(canvasId)
}
}
}
},
fail(errorMsg){
console.log(errorMsg)
}
})
}
},
// 生成海报并分享给好友
//将canvas转换为图片保存到本地,然后将图片路径传给image图片的src
createNewImg: function (url, canvasId) {
console.log('createNewImg')
console.log(canvasId)
var that = this;
const context = wx.createCanvasContext(canvasId)
context.setFillStyle('white')
context.fillRect(30, 10, 300, 500)
context.draw()
var path = url;
//将模板图片绘制到canvas,在开发工具中drawImage()函数有问题,不显示图片
context.drawImage(path, 30, 10, 330, 310);
var path1 = this.data.codeUrl;
//二维码
context.drawImage(path1, 250, 330, 70, 70);
//不知道是什么原因,手机环境能正常显示
context.save(); // 保存当前context的状态
//绘制商品对应的品牌名称
context.setFontSize(12);
context.setFillStyle('#000000');
context.setTextAlign('left');
context.fillText(that.data.proNo, 40, 350);
context.fillText(that.data.price+'元', 40, 370)
context.stroke();
context.setFontSize(10)
context.setTextAlign('right')
context.fillText(that.data.scan, 320, 410)
context.draw(true,()=>{
console.log('ondraw================')
})
},
saveimg: function (canvasId) {
let that = this;
// 授权放置在相册里面
wx.getSetting({
success(res) {
if (!res.authSetting['scope.writePhotosAlbum']) {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success() {
// 用户已经同意小程序相册功能,后续调用 wx.saveImageToPhotosAlbum 接口不会弹窗询问
that.saveablum(canvasId)
},
fail() {
that.setData({
openauthpop: true
});
// that.handleSetting(res);
}
})
} else {
that.saveablum(canvasId)
}
}
});
},
saveablum: function (canvasId) {
var that = this
let imageWidth = this.data.imageWidth,
imageHeight = this.data.imageHeight;
wx.canvasToTempFilePath({ //将canvas生成图片
canvasId: canvasId,
x: 30,
y: 0,
width: imageWidth,
height: imageHeight,
destWidth: imageWidth*3, //截取canvas的宽度
destHeight: imageHeight*3, //截取canvas的高度
success: function (res) {
wx.saveImageToPhotosAlbum({ //保存图片到相册
filePath: res.tempFilePath,
success: function () {
wx.showToast({
title: "图片保存成功!",
duration: 2000
})
let count = that.data.downloadCount + 1
if(count == that.data.picList.length){
wx.hideLoading()
wx.navigateBack({
delta: 0,
})
}
that.setData({
downloadCount:count
})
},
fail: function () {
},
})
},
fail: function (res) {
console.log(res);
}
})
},
})
index.wxss
page{
width: 100%;
height: 100%;
background: #eeeeee;
}
.root{
display: flex;
flex-direction: column;
}
.swiper{
height: 450px;
width: 100%;
}
.canvas{
width: 330px;
height: 420px;
}
.image{
width: 600rpx;
height: 600rpx;
}
.item_container{
display: flex;
flex-direction: column;
background: white;
margin: 20rpx 10rpx;
}
.image_container{
display: flex;
align-items: center;
justify-content: center;
}
.info_container{
display: flex;
flex-direction: row;
align-items: center;
margin-top: 30rpx;
}
.info_no{
display: flex;
flex-direction: column;
flex: 1;
margin-left: 30rpx;
}
.tv_info{
font-size: 28rpx;
color: #333333;
}
.code{
width: 140rpx;
height: 140rpx;
}
.info_image{
display: flex;
flex-direction: column;
margin-left: 30rpx;
margin-bottom: 20rpx;
margin-right: 20rpx;
}
.code_tip{
font-size: 20rpx;
color: #333333;
}
.bottom{
position: fixed;
bottom: 0;
display: flex;
flex-direction: column;
width: 100%;
}
.bottom_content{
background: white;
display: flex;
flex-direction: column;
}
.btn_container{
display: flex;
flex: 1;
padding: 30rpx 60rpx;
}
.cancel{
font-size: 28rpx;
color: red;
border-top: 1rpx solid #eeeeee;
display: flex;
align-items: center;
justify-content: center;
height: 90rpx;
}
.item_btn{
display: flex;
flex-direction: column;
margin-right: 60rpx;
}
.item_btn image{
width: 80rpx;
height: 80rpx;
}
.item_btn view{
font-size: 20rpx;
color: #777777;
}
.canvas_container{
display: flex;
background: white;
}
index.wxml
<scroll-view scroll-x="true">
<view class="root">
<block wx:for="{{picList}}" wx:for-index="index">
<canvas canvas-id="canvas{{index}}" class="canvas"></canvas>
</block>
</view>
</scroll-view>