Use canvas to share two-dimensional code on the H5 page of the small program. The effect as shown below can be saved and scanned
General idea: Canvas is used for drawing. In order to save time, the fixed part is drawn with the background image, only the TWO-DIMENSIONAL code and the display picture and title. After drawing, call uni.canvastotempFilepath to turn it into a picture display
1. Component invocation: use ref to call the corresponding canvas drawing method inside the component, and pass in relevant parameters including name, route, display picture, etc.
<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>
Copy the code
2. The component template places the Canvas container and assigns the ID, width, height, etc. Use isComplete to control whether to display the canvas or the image generated by the last call to 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>
Copy the code
3. Set parameters in data
data() {
return {
bgImg:'https://cdn.img.up678.com/ueditor/upload/image/20211130/1638258070231028289.png'.// Canvas background image
cansWidth:288.// Canvas width
cansHeight:410.// Canvas height
projectImgWidth:223.// Show the width of the image in the middle
projectImgHeight:167.// Show the height of the image in the middle
qrShow:true.// Two-dimensional canvas
qrData: null.// Code data
tempFilePath:' '.// Generate graph path
iscomplete:false.// Whether to generate a picture}},Copy the code
4. Call uni.createCanvasContext during the Created life cycle to create a Canvas instance and pass in the canvas container ID within the template
created(){
this.ctx = uni.createCanvasContext('poster'.this)},Copy the code
5. Call corresponding methods to draw shared works
// Draw shared works
async drawposter(name='The Most Beautiful University scene in Chongqing',url,projectImg){
uni.showLoading({
title: "Loading...".mask: true
})
// Generate a QR code
await this.createQrcode(url)
/ / the background
await this.drawWebImg({
url: this.bgImg,
x: 0.y: 0.width: this.cansWidth, height: this.cansHeight
})
/ / display figure
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)'}})// Draw a qr code
await this.drawQrcode()
// Convert to image
this.tempFilePath = await this.saveCans()
this.iscomplete = true
uni.hideLoading()
},
Copy the code
6. DrawImage method: note that the first parameter of this.ctx. DrawImage method cannot be used to display network images
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)
}
})
})
},
Copy the code
7. Draw text titles
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()
})
})
},
// Text header overflow hide processing
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;
}
returnstr + ellipsis; }},Copy the code
8. Generate a QR code
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)
}
})
},
Copy the code
9. Draw the QR code. This. qrData is the generated QR code resource
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()
})
})
},
Copy the code
10. Convert canvas contents into images and display them. On H5, tempFilePath is 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)})},Copy the code
11. All code of the component
<template>
<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>
</template>
<script>
import qrCode from '@/utils/wxqrcode.js'
export default {
data() {
return {
bgImg:'https://cdn.img.up678.com/ueditor/upload/image/20211130/1638258070231028289.png'.// Canvas background image
cansWidth:288.// Canvas width
cansHeight:410.// Canvas height
projectImgWidth:223.// Show the width of the image in the middle
projectImgHeight:167.// Show the height of the image in the middle
schoolImgWidth:110.// The middle shows the width of the college
schoolImgHeight:110.// Show the height of the university in the middle
qrShow:true.// Two-dimensional canvas
qrData: null.// Code data
tempFilePath:' '.// Generate graph path
iscomplete:false.// Whether to generate a picture}},created(){
this.ctx = uni.createCanvasContext('poster'.this)},methods: {closePoster(e) {
if(e.target.id === e.currentTarget.id) {
/ / close
this.$emit('close')}},// Draw shared works
async drawposter(name='The Most Beautiful University scene in Chongqing',url,projectImg){
uni.showLoading({
title: "Loading...".mask: true
})
await this.createQrcode(url)
/ / the background
await this.drawWebImg({
url: this.bgImg,
x: 0.y: 0.width: this.cansWidth, height: this.cansHeight
})
/ / display figure
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)'}})/ / qr code
await this.drawQrcode()
this.tempFilePath = await this.saveCans()
this.iscomplete = true
uni.hideLoading()
},
// Draw share school
async drawposterschool(name,url,schoolImg){
uni.showLoading({
title: "Loading...".mask: true
})
await this.createQrcode(url)
/ / the background
await this.drawWebImg({
url: this.bgImg,
x: 0.y: 0.width: this.cansWidth, height: this.cansHeight
})
/ / display figure
await this.drawSchoolImg({
url: schoolImg,
x: 90.y: 120.width: this.schoolImgWidth, height: this.schoolImgHeight
})
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)'}})/ / qr code
await this.drawQrcode()
this.tempFilePath = await this.saveCans()
this.iscomplete = true
uni.hideLoading()
},
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)
}
})
})
},
drawSchoolImg(conf) {
return new Promise((resolve, reject) = > {
uni.downloadFile({
url: conf.url,
success: (res) = > {
this.ctx.save()
this.ctx.beginPath()
this.ctx.arc(135.170.70.0.2 * Math.PI)
// this.ctx.setFillStyle('blue')
// this.ctx.fill()
this.ctx.clip();
this.ctx.drawImage(res.tempFilePath, conf.x, conf.y, conf.width, conf.height)
this.ctx.restore()
this.ctx.draw(true.() = > {
resolve()
})
},
fail: err= > {
reject(err)
}
})
})
},
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;
}
returnstr + ellipsis; }},// Draw the qr code
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()
})
})
},
// Generate a QR code
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)
}
})
},
// 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)})},}}</script>
<style lang="stylus" scoped>
.poster-wrapper{
width 100vw
height 100vh
position fixed
background rgba(0.0.0.4)
left 0
top 0
text-align center
z-index 99999
.poster-content{
position absolute
top 50%
left 50%
transform translate(-50%, -50%)}}</style>
Copy the code