在uniapp中实现微信小程序保存海报到手机相册,主要涉及Canvas绘制和图片保存。以下是关键步骤和代码示例:
一、关键代码展示:
1. 模板配置:页面展示该海报,可直接查看,也可下载保存到手机相册,html关键代码如下:
<view class="content">
<canvas class="canvas-poster" canvas-id="canvasposter"></canvas>
</view>
2. 海报绘制:js关键代码如下:
//绘制到canvas
downloadQrcode: function() {
var ctx = uni.createCanvasContext("canvasposter")
let that = this
// #ifdef MP-WEIXIN
uni.downloadFile({
url: 'https://xxx.zexun.tech/getfile/statics/cdn/images/large_invite_bg.png', // 网络图片链接
success: downloadResult => {
if (downloadResult.statusCode === 200) {
/* 绘制第一张照片*/
// 参数说明:('图片路径',canvas的横坐标,canvas的纵坐标,图片的宽度,图片的宽度)
ctx.drawImage(downloadResult.tempFilePath, 0, 0, 750, 1624)
// 绘制第二张图片-base64-转换真机可读
wx.getFileSystemManager().writeFile({
filePath: wx.env.USER_DATA_PATH + "/test.png",
data: that.codeBase64,
encoding: 'base64',
success: (res) => {
ctx.drawImage(wx.env.USER_DATA_PATH + "/test.png", 164,
816, 420, 420)
ctx.setTextAlign("center")
ctx.setFontSize(34) // 第一行文字
ctx.fillStyle = '#2B5370'; // 设置文字颜色为白色
ctx.fillText('我的邀请码:'+ that.$userInfo.agentNo, 375,
668) //文字内容、x坐标,y坐标
ctx.setFontSize(26) // 第二行文字
ctx.fillStyle = '#636D86'; // 设置文字颜色为白色
ctx.fillText('扫一扫下方二维码,成为我的业务伙伴', 365,
782) //文字内容、x坐标,y坐标
uni.showLoading({
title: "图片生成中...",
})
ctx.draw(
false,
setTimeout(() => {
that.getTempFilePath()
}, 2500)
)
}
})
}
},
fail: () => {
uni.showToast({
title: '下载失败',
icon: 'none'
});
}
});
// #endif
},
//获取临时路径
getTempFilePath: function() {
// 当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径
uni.canvasToTempFilePath({
canvasId: "canvasposter",
success: (res) => {
console.log(res.tempFilePath)
this.saveImageToPhotosAlbum(res.tempFilePath) //保存到相册
},
})
},
//把生成的图片保存至相册
saveImageToPhotosAlbum: function(imgUrl) {
uni.hideLoading()
if (imgUrl) {
uni.saveImageToPhotosAlbum({
filePath: imgUrl,
success: (res) => {
uni.showToast({
title: "保存成功",
icon: "success",
duration: 2000,
})
},
fail: (err) => {
uni.showToast({
title: "保存失败",
icon: "none",
duration: 2000,
})
},
})
} else {
uni.showToast({
title: "绘制中……",
icon: "loading",
duration: 3000,
})
}
},
3. 样式css关键代码如下:
/* 绘制图片canvas样式 */
.canvas-poster {
position: fixed;
width: 750px;
height: 1624px;
top: 100%;
left: 100%;
}
二、完整代码附录:
<template>
<view class="content">
<!-- #ifdef MP-WEIXIN -->
<view class="guide_header_page2">
<view :style="{ height: statusBarHeight }"></view>
<view class="guide_title" :style="{ height: navigationBarHeight, lineHeight:navigationBarHeight }">
<uni-icons type="back" size="22" color="#232323" @click="goBack" class="icon"></uni-icons>
<text>我的邀请码</text>
</view>
</view>
<!-- #endif -->
<view class="invite">
<image src="https://xxx.zexun.tech/getfile/statics/cdn/images/large_invite_bg.png" mode="widthFix"
class="bg" />
<view class="invite_title">我的邀请码:{{$userInfo.agentNo}}</view>
<view class="invite_tip">
扫一扫下方二维码,成为我的业务伙伴
</view>
<image :src="'data:image/png;base64,' + codeBase64" mode="widthFix" class="qrcode" />
<view class="invite_btn">
<u-button text="保存图片" shape="circle" color="linear-gradient(to right, #26B6B9, #21CE98)" @click="downloadQrcode"></u-button>
</view>
</view>
<canvas class="canvas-poster" canvas-id="canvasposter"></canvas>
</view>
</template>
<script>
import {
getInvitationCode
} from '@/common/api.js'
export default {
data() {
return {
// #ifdef MP-WEIXIN
statusBarHeight: uni.getSystemInfoSync().statusBarHeight + 'px', // 状态栏高度
capBarHeight: uni.getMenuButtonBoundingClientRect().height + 'px', // 胶囊高度
navigationBarHeight: (uni.getMenuButtonBoundingClientRect().top - uni.getSystemInfoSync()
.statusBarHeight) * 2 + uni.getMenuButtonBoundingClientRect().height + 'px', // 导航栏高度
barCapHeight: (uni.getMenuButtonBoundingClientRect().top - uni.getSystemInfoSync()
.statusBarHeight) * 2 + uni.getMenuButtonBoundingClientRect().height + uni.getSystemInfoSync()
.statusBarHeight + 'px', //导航栏高度+状态栏高度
// #endif
codeBase64: null,
type: '2', // 2-服务商邀请码,3-业务员邀请码
}
},
onLoad() {
this.getInvitationCode()
},
methods: {
goBack() {
uni.navigateBack()
},
// 获取二维码
getInvitationCode() {
uni.showLoading({
mask: true
})
getInvitationCode({
inviteCode: this.$store.state.$userInfo.agentId,
type: this.type
})
.then((res) => {
uni.hideLoading()
this.codeBase64 = res.data
})
.catch((err) => {
uni.hideLoading()
console.log(err)
})
},
//绘制到canvas
downloadQrcode: function() {
var ctx = uni.createCanvasContext("canvasposter")
let that = this
// #ifdef MP-WEIXIN
uni.downloadFile({
url: 'https://xxx.zexun.tech/getfile/statics/cdn/images/large_invite_bg.png', // 网络图片链接
success: downloadResult => {
if (downloadResult.statusCode === 200) {
/* 绘制第一张照片*/
// 参数说明:('图片路径',canvas的横坐标,canvas的纵坐标,图片的宽度,图片的宽度)
ctx.drawImage(downloadResult.tempFilePath, 0, 0, 750, 1624)
// 绘制第二张图片-base64-转换真机可读
wx.getFileSystemManager().writeFile({
filePath: wx.env.USER_DATA_PATH + "/test.png",
data: that.codeBase64,
encoding: 'base64',
success: (res) => {
ctx.drawImage(wx.env.USER_DATA_PATH + "/test.png", 164,
816, 420, 420)
ctx.setTextAlign("center")
ctx.setFontSize(34) // 第一行文字
ctx.fillStyle = '#2B5370'; // 设置文字颜色为白色
ctx.fillText('我的邀请码:'+ that.$userInfo.agentNo, 375,
668) //文字内容、x坐标,y坐标
ctx.setFontSize(26) // 第二行文字
ctx.fillStyle = '#636D86'; // 设置文字颜色为白色
ctx.fillText('扫一扫下方二维码,成为我的业务伙伴', 365,
782) //文字内容、x坐标,y坐标
uni.showLoading({
title: "图片生成中...",
})
ctx.draw(
false,
setTimeout(() => {
that.getTempFilePath()
}, 2500)
)
}
})
}
},
fail: () => {
uni.showToast({
title: '下载失败',
icon: 'none'
});
}
});
// #endif
// #ifndef MP-WEIXIN
/* 绘制第一张照片*/
// 参数说明:('图片路径',canvas的横坐标,canvas的纵坐标,图片的宽度,图片的宽度)
ctx.drawImage("https://jsfzapi.zexun.tech/getfile/statics/cdn/images/invite_bg.png", 0, 0,
750, 1624)
/* 绘制第二张照片*/
ctx.drawImage("data:image/png;base64," + this.codeBase64, 164, 912, 420, 420)
ctx.setTextAlign("center")
ctx.setFontSize(32)
ctx.setTextAlign("center")
ctx.fillText(this.$realAgentInfo.shortName, 375, 880) //文字内容、x坐标,y坐标
uni.showLoading({
title: "图片生成中...",
})
ctx.draw(
false,
setTimeout(() => {
this.getTempFilePath()
}, 1500)
)
// #endif
},
//获取临时路径
getTempFilePath: function() {
// 当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径
uni.canvasToTempFilePath({
canvasId: "canvasposter",
success: (res) => {
console.log(res.tempFilePath)
this.saveImageToPhotosAlbum(res.tempFilePath) //保存到相册
},
})
},
//把生成的图片保存至相册
saveImageToPhotosAlbum: function(imgUrl) {
uni.hideLoading()
if (imgUrl) {
uni.saveImageToPhotosAlbum({
filePath: imgUrl,
success: (res) => {
uni.showToast({
title: "保存成功",
icon: "success",
duration: 2000,
})
},
fail: (err) => {
uni.showToast({
title: "保存失败",
icon: "none",
duration: 2000,
})
},
})
} else {
uni.showToast({
title: "绘制中……",
icon: "loading",
duration: 3000,
})
}
},
},
}
</script>
<style lang="scss" scoped>
/* 绘制图片canvas样式 */
.canvas-poster {
position: fixed;
width: 750px;
height: 1624px;
top: 100%;
left: 100%;
}
.content {
.invite {
width: 100%;
position: relative;
.bg {
width: 750rpx;
}
.invite_title {
min-width: 418rpx;
position: absolute;
left: 52%;
transform: translateX(-50%);
top: 630rpx;
font-weight: bold;
font-size: 34rpx;
color: #2B5370;
}
.invite_tip {
min-width: 442rpx;
position: absolute;
left: 50%;
transform: translateX(-50%);
top: 766rpx;
font-weight: 500;
font-size: 26rpx;
color: #636D86;
}
.qrcode {
width: 420rpx;
height: 420rpx;
left: 50%;
transform: translateX(-50%);
top: 830rpx;
position: absolute;
}
.invite_btn {
width: 484rpx;
height: 76rpx;
bottom: 176rpx;
position: absolute;
z-index: 999;
left: 50%;
transform: translateX(-50%);
}
}
}
</style>
三、效果图展示:
提示:使用 uni.downloadFile 下载网络图片 https://xxx.xxx 等,需要在小程序后台配置服务器域名;
有什么疑问,可以评论区回复,大家一起探讨~