uniapp使用canvas实现二维码分享
实现使用canvas在小程序H5页面进行二维码分享 如下图效果 可以保存并扫码
总体思路:使用canvas进行绘制,为了节省时间固定部分采用背景图绘制 只有二维码以及展示图片及标题绘制,绘制完成后调用uni.canvasToTempFilePath将其转为图片展示
1.组件调用,使用ref调用组件内部相应的canvas绘制方法,传入相关参数 包括名称 路由 展示图片等。
<SharePoster v-if='showposter' ref='poster' @close='close'/>
<script>
import SharePoster from "@/components/share/shareposter.vue"
export default {
components: {
SharePoster,
},
methods:{
handleShare(item){
this.showposter=true
if(this.showvote){
this.showvote=false
}
this.$nextTick(() => {
this.$refs.poster.drawposter(item.name, `/pagesMore/voluntary/video/player?schoolId=${item.id}`,item.cover)
})
},
}
</script>
2.组件模板放置canvas容器并赋予id以及宽度高度等,使用iscomplete控制是显示canvas还是显示最后调用uni.canvasToTempFilePath生成的图片
<div class="poster-wrapper" @click="closePoster($event)">
<div class='poster-content'>
<canvas canvas-id="qrcode"
v-if="qrShow"
:style="{opacity: 0, position: 'absolute', top: '-1000px'}"
></canvas>
<canvas
canvas-id="poster"
:style="{ width: cansWidth + 'px', height: cansHeight + 'px' ,opacity: 0, }"
v-if='!iscomplete'
></canvas>
<image
v-if="iscomplete"
:style="{ width: cansWidth + 'px', height: cansHeight + 'px' }"
:src="tempFilePath"
@longpress="longpress"
></image>
</div>
</div>
3.data内放置相应配置参数
data() {
return {
bgImg:'https://cdn.img.up678.com/ueditor/upload/image/20211130/1638258070231028289.png', //画布背景图片
cansWidth:288, // 画布宽度
cansHeight:410, // 画布高度
projectImgWidth:223, // 中间展示图片宽度
projectImgHeight:167, // 中间展示图片高度
qrShow:true, // 二维码canvas
qrData: null, // 二维码数据
tempFilePath:'',// 生成图路径
iscomplete:false, // 是否生成图片
}
},
4.在created生命周期内调用uni.createCanvasContext创建canvas实例 传入模板内canvas容器id
created(){
this.ctx = uni.createCanvasContext('poster',this)
},
5.调用对应方法,绘制分享作品
// 绘制分享作品
async drawposter(name='重庆最美高校景象',url,projectImg){
uni.showLoading({
title: "加载中...",
mask: true
})
// 生成二维码
await this.createQrcode(url)
// 背景
await this.drawWebImg({
url: this.bgImg,
x: 0, y: 0, width: this.cansWidth, height: this.cansHeight
})
// 展示图
await this.drawWebImg({
url: projectImg,
x: 33, y: 90, width: this.projectImgWidth, height: this.projectImgHeight
})
await this.drawText({
text: name,
x: 15, y: 285, color: '#241D4A', size: 15, bold: true, center: true,
shadowObj: {x: '0', y: '4', z: '4', color: 'rgba(173,77,0,0.22)'}
})
// 绘制二维码
await this.drawQrcode()
//转为图片
this.tempFilePath = await this.saveCans()
this.iscomplete = true
uni.hideLoading()
},
6.绘制图片方法,注意 this.ctx.drawImage方法第一个参数不能放网络图片 必须执行下载后绘制
drawWebImg(conf) {
return new Promise((resolve, reject) => {
uni.downloadFile({
url: conf.url,
success: (res) => {
this.ctx.drawImage(res.tempFilePath, conf.x, conf.y, conf.width?conf.width:"", conf.height?conf.height:"")
this.ctx.draw(true, () => {
resolve()
})
},
fail: err => {
reject(err)
}
})
})
},
7.绘制文本标题
drawText(conf) {
return new Promise((resolve, reject) => {
this.ctx.restore()
this.ctx.setFillStyle(conf.color)
if(conf.bold) this.ctx.font = `normal bold ${conf.size}px sans-serif`
this.ctx.setFontSize(conf.size)
if(conf.shadowObj) {
// this.ctx.shadowOffsetX = conf.shadowObj.x
// this.ctx.shadowOffsetY = conf.shadowObj.y
// this.ctx.shadowOffsetZ = conf.shadowObj.z
// this.ctx.shadowColor = conf.shadowObj.color
}
let x = conf.x
conf.text=this.fittingString(this.ctx,conf.text,280)
if(conf.center) {
let len = this.ctx.measureText(conf.text)
x = this.cansWidth / 2 - len.width / 2 + 2
}
this.ctx.fillText(conf.text, x, conf.y)
this.ctx.draw(true, () => {
this.ctx.save()
resolve()
})
})
},
// 文本标题溢出隐藏处理
fittingString(_ctx, str, maxWidth) {
let strWidth = _ctx.measureText(str).width;
const ellipsis = '…';
const ellipsisWidth = _ctx.measureText(ellipsis).width;
if (strWidth <= maxWidth || maxWidth <= ellipsisWidth) {
return str;
} else {
var len = str.length;
while (strWidth >= maxWidth - ellipsisWidth && len-- > 0) {
str = str.slice(0, len);
strWidth = _ctx.measureText(str).width;
}
return str + ellipsis;
}
},
8.生成二维码
createQrcode(qrcodeUrl) {
// console.log(window.location.origin)
const config={host:window.location.origin}
return new Promise((resolve, reject) => {
let url = `${config.host}${qrcodeUrl}`
// if(url.indexOf('?') === -1) url = url + '?sh=1'
// else url = url + '&sh=1'
try{
new qrCode({
canvasId: 'qrcode',
usingComponents: true,
context: this,
// correctLevel: 3,
text: url,
size: 130,
cbResult: (res) => {
this.qrShow = false
this.qrData = res
resolve()
}
})
} catch (err) {
reject(err)
}
})
},
9.画二维码,this.qrData为生成的二维码资源
drawQrcode(conf = { x: 185, y: 335, width: 100, height: 50}) {
return new Promise((resolve, reject) => {
this.ctx.drawImage(this.qrData, conf.x, conf.y, conf.width, conf.height)
this.ctx.draw(true, () => {
resolve()
})
})
},
10.将canvas绘制内容转为图片并显示,在H5平台下,tempFilePath 为 base64
// canvs => images
saveCans() {
return new Promise((resolve, reject) => {
uni.canvasToTempFilePath({
x:0,
y:0,
canvasId: 'poster',
success: (res) => {
resolve(res.tempFilePath)
},
fail: (err) => {
uni.hideLoading()
reject(err)
}
}, this)
})
},
11.组件全部代码
作者:ArvinC
来源:juejin.cn/post/7041087990222815246