代码:
<canvas type="2d" canvas-id="myCanvas" id="myCanvas" style="width: 332px;height: 601px;position: fixed;top: -10000px;"></canvas>
<image wx:if="{{certificationImg}}" class="certification-image" src="{{certificationImg}}" bindtap="previewImg" />
.certification-image {
width: 664rpx;
height: 1202rpx;
box-shadow: 0 10rpx 20rpx 0 rgba(0,0,0,0.5);
}
generateCertification () {
wx.showLoading({
title: '正在生成证书',
mask: true
})
this.createCertification();
setTimeout(() => {
// 将生成的canvas图片,转为真实图片
const query = wx.createSelectorQuery();
query.select('#myCanvas')
.fields({ node: true, size: true })
.exec((res) => {
const canvas = res[0].node;
wx.canvasToTempFilePath({
canvasId: 'myCanvas',
canvas: canvas,
success: async (res) => {
this.setData({
certificationImg: res.tempFilePath,
showCertification: true
})
wx.hideLoading();
},
fail: (res) => {
console.log(res);
}
})
})
}, 500)
},
previewImg () {
wx.previewImage({
current: this.data.certificationImg,
urls: [this.data.certificationImg]
})
}
createCertification () {
const query = wx.createSelectorQuery();
query.select('#myCanvas')
.fields({ node: true, size: true })
.exec((res) => {
const canvas = res[0].node;
const ctx = canvas.getContext('2d');
const dpr = wx.getSystemInfoSync().pixelRatio;
canvas.width = res[0].width * dpr;
canvas.height = res[0].height * dpr;
ctx.scale(dpr, dpr);
ctx.save();
// 绘制背景图片
let bg = canvas.createImage();
bg.src = '/img/certification/bg.png';
bg.onload = () => {
ctx.drawImage(bg, 0, 0, 332, 601);
// 绘制无驾车票等你来领图片
let waitPic = canvas.createImage();
waitPic.src = '/img/certification/wait_you_white.png';
waitPic.onload = () => {
ctx.drawImage(waitPic, 27, 11, 270, 129);
}
// 绘制信息白色背景
let whiteBg = canvas.createImage();
whiteBg.src = '/img/certification/white_ticket_bg.png';
whiteBg.onload = () => {
ctx.drawImage(whiteBg, 17, 149, 303, 378);
// 绘制用户上传的图片
let pic = canvas.createImage();
pic.src = this.data.photo || this.data.defaultCarImg;
pic.onload = () => {
ctx.save();
this.roundRect(ctx, 33, 180, 267, 157, 5);
ctx.drawImage(pic, 33, 180, 267, 157);
ctx.restore();
}
// 绘制乘客人数
ctx.save();
this.roundRect(ctx, 33, 353, 270, 42, 4);
ctx.rect(33, 353, 270, 42);
ctx.fillStyle = '#027CFF';
ctx.fill();
ctx.restore();
let passengerNum = this.data.trip.count + '';
let passengerText = `无人驾驶第${passengerNum}位乘客`;
let lettersWidth = 0;
let passengerTextArr = passengerText.split("");
passengerTextArr.forEach((letter, index) => {
let letterWidth = 0;
if (index > 4 && index < passengerTextArr.length - 3) {
ctx.font = 'normal normal 21px sans-serif';
ctx.fillStyle = '#EFBC06';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
letterWidth = ctx.measureText(letter).width;
ctx.fillText(letter, lettersWidth + (332/2 - ctx.measureText(passengerText).width / 2) + letterWidth + (passengerNum.length - 5) * 0.6, 376);
} else {
ctx.font = 'normal normal 18px sans-serif';
ctx.fillStyle = '#FFFFFF';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(letter, lettersWidth + (332/2 - ctx.measureText(passengerText).width / 2), 376);
letterWidth = ctx.measureText(letter).width + 1.3;
}
lettersWidth = lettersWidth + letterWidth;
})
// 绘制乘客行程信息
ctx.font = 'normal normal 10px PingFangSC-Regular';
ctx.fillStyle = '#027CFF';
ctx.textAlign = 'left';
ctx.fillText('乘客', 45, 419);
ctx.font = 'normal normal 10px PingFangSC-Regular';
ctx.fillStyle = '#027CFF';
ctx.textAlign = 'left';
ctx.fillText('总行程', 142, 419);
ctx.font = 'normal normal 10px PingFangSC-Regular';
ctx.fillStyle = '#027CFF';
ctx.textAlign = 'left';
ctx.fillText('用时', 222, 419);
ctx.font = 'normal normal 13px sans-serif';
ctx.fillStyle = '#24355A';
ctx.textAlign = 'left';
ctx.fillText(this.data.passengerName, 45, 442);
ctx.font = 'normal normal 13px sans-serif';
ctx.fillStyle = '#24355A';
ctx.textAlign = 'left';
ctx.fillText(this.data.trip.totalDistance, 142, 442);
ctx.font = 'normal normal 13px sans-serif';
ctx.fillStyle = '#24355A';
ctx.textAlign = 'left';
ctx.fillText(this.data.trip.duration, 222, 442);
// 起点
let endIcon = canvas.createImage();
endIcon.src = '/img/certification/start_icon.png';
endIcon.onload = () => {
ctx.drawImage(endIcon, 45, 474, 11, 13);
ctx.font = 'normal normal 13x sans-serif';
ctx.fillStyle = '#24355A';
ctx.textAlign = 'left';
ctx.fillText(this.data.trip.start.name, 70, 482);
}
// 终点
let startIcon = canvas.createImage();
startIcon.src = '/img/certification/end_icon.png';
startIcon.onload = () => {
ctx.drawImage(startIcon, 43, 500, 13, 13);
ctx.font = 'normal normal 13x sans-serif';
ctx.fillStyle = '#24355A';
ctx.textAlign = 'left';
ctx.fillText(this.data.trip.destination.name, 70, 508);
}
}
// 底部icon
let zzxLogo = canvas.createImage();
zzxLogo.src = '/img/logo.png';
zzxLogo.onload = () => {
ctx.drawImage(zzxLogo, 128, 550, 75, 34);
}
ctx.save();
}
})
},
/**
*
* @param {CanvasContext} ctx canvas上下文
* @param {number} x 圆角矩形选区的左上角 x坐标
* @param {number} y 圆角矩形选区的左上角 y坐标
* @param {number} w 圆角矩形选区的宽度
* @param {number} h 圆角矩形选区的高度
* @param {number} r 圆角的半径
*/
roundRect(ctx, x, y, w, h, r) {
// 开始绘制
ctx.beginPath()
ctx.fillStyle = 'transparent'
// 左上角
ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)
// border-top
ctx.moveTo(x + r, y)
ctx.lineTo(x + w - r, y)
ctx.lineTo(x + w, y + r)
// 右上角
ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)
// border-right
ctx.lineTo(x + w, y + h - r)
ctx.lineTo(x + w - r, y + h)
// 右下角
ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)
// border-bottom
ctx.lineTo(x + r, y + h)
ctx.lineTo(x, y + h - r)
// 左下角
ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)
// border-left
ctx.lineTo(x, y + r)
ctx.lineTo(x + r, y)
ctx.fill()
ctx.closePath()
// 剪切
ctx.clip()
}
// 保存图片相关权限
savePicture () {
wx.showLoading({
title: '正在保存图片',
mask: true
});
// 判断用户是否授权”保存到相册“
wx.getSetting({
success: (res) => {
//没有权限,发起授权
if (!res.authSetting['scope.writePhotosAlbum']) {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success: () => {
//用户允许授权,保存图片到相册
this.savePhoto();
},
fail() {
//用户点击拒绝授权,跳转到设置页,引导用户授权
wx.showModal({
title: '提示',
content: '您好,请先授权,再保存此图片。',
showCancel: true,
cancelText: '取消',
cancelColor: '#000000',
confirmColor: '#027CFF',
success: res => {
if (res.confirm) {
wx.openSetting({
success: () => {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success: () => {
this.savePhoto();
}
})
},
fail: (res) => {
console.log(res);
}
})
} else if (res.cancel) {
wx.showToast({
title: '需要保存图片权限',
icon: 'none',
duration: 2000,
})
}
}
});
wx.hideLoading()
}
});
} else {
//用户已授权,保存到相册
this.savePhoto();
}
},
fail: (res) => {
wx.hideLoading()
console.log(res);
}
});
},
// 先下载再保存到相册
savePhoto() {
let certificationImg = this.data.certificationImg
if (this.data.isNetworkPic) {
wx.downloadFile({
url: certificationImg,
success: (res) => {
if (res && res.statusCode === 200) {
certificationImg = res.tempFilePath
}
},
fail: () => {
wx.hideLoading()
wx.showToast({
title: '下载失败',
icon: 'none',
duration: 1000
})
}
})
}
wx.saveImageToPhotosAlbum({
filePath: certificationImg,
success: () => {
wx.hideLoading()
wx.showToast({
title: '保存成功',
icon: 'success',
duration: 1000
})
},
fail: () => {
wx.hideLoading()
wx.showToast({
title: '保存失败',
icon: 'none',
duration: 1000
})
}
})
},