微信小程序-二维码绘制
wxml
<view bindlongtap="saveQrcode">
<!-- 二维码 -->
<view style="position: absolute;background-color: #FFFAEC;width: 100%;height: 100vh;">
<canvas canvas-id="myQrcode" style="width: 200px; height: 200px;background-color: azure;position: fixed;top: 999px;" ></canvas>
</view>
<!-- 绘制的背景图 -->
<canvas type="2d" id="newQrcode" style="width: 100%;height: 700px;z-index: 99;"></canvas>
</view>
wxss
/* pages/QRcode/QRcode.wxss */
.canvas {
width: 100%;
height: -webkit-calc(100% - 44px);
height: -moz-calc(100% - 44px);
height: calc(100% - 44px);
background: #fff;
}
js
// pages/index/index.js
import QRCode from './weapp.qrcode.esm';
let textCanvas;
Page({
data: {
qrcodeVisible: true // 控制二维码是否显示
},
onReady() {
// 等待二维码绘制完成后再获取临时文件路径
this.generateQRCode().then((tempQrcodePath) => {
this.drawCompositeImage(tempQrcodePath);
}).catch((err) => {
console.error('生成二维码临时文件失败:', err);
wx.showToast({
title: '生成二维码临时文件失败',
icon: 'none'
});
});
},
// 生成二维码并获取临时文件路径
generateQRCode() {
return new Promise((resolve, reject) => {
// 初始化二维码
QRCode({
width: 200,
height: 200,
canvasId: 'myQrcode',
colorDark: '#000000',
colorLight: '#ffffff',
text: 'http://lxj.yzwdblzs.xyz/',
});
// 延迟一段时间确保二维码绘制完成,可根据实际情况调整延迟时间
setTimeout(() => {
wx.canvasToTempFilePath({
canvasId: 'myQrcode',
success: (res) => {
console.log('二维码路径:', res);
const tempQrcodePath = res.tempFilePath;
resolve(tempQrcodePath);
},
fail: (err) => {
console.error('获取临时文件失败', err);
reject(err);
}
});
}, 500);
});
},
drawCompositeImage(tempQrcodePath) {
return new Promise((resolve, reject) => {
wx.createSelectorQuery().select('#newQrcode')
.fields({
node: true,
size: true
})
.exec((res) => {
textCanvas = res[0].node; // 获取 canvas 节点
const textCtx = textCanvas.getContext('2d');
const dpr = wx.getSystemInfoSync().pixelRatio; // 获取设备像素比
textCanvas.width = res[0].width * dpr;
textCanvas.height = res[0].height * dpr;
textCtx.scale(1, 1);
textCtx.fillRect(0, 0, 200, 200);
textCtx.clearRect(0, 0, textCanvas.width, textCanvas.height);
textCtx.beginPath();
const bg = textCanvas.createImage();
bg.src = 'http://lxj.yzwdblzs.xyz/img/noName.png';
bg.onload = () => {
console.log('背景图加载成功');
const qrImage = textCanvas.createImage();
qrImage.src = tempQrcodePath;
qrImage.onload = () => {
console.log('二维码加载成功');
// 绘制背景图
this.drawBackground(textCtx, bg);
// 绘制二维码
this.drawQRCode(textCtx, tempQrcodePath);
resolve();
};
qrImage.onerror = () => {
console.error('二维码加载失败');
reject(new Error('二维码加载失败'));
};
};
bg.onerror = () => {
console.error('背景图加载失败');
reject(new Error('背景图加载失败'));
};
});
});
},
drawBackground(textCtx, bg) {
const bgWidth = bg.width;
const bgHeight = bg.height;
// 计算缩放比例
const scaleX = textCanvas.width / bgWidth;
const scaleY = textCanvas.height / bgHeight;
const scale = Math.max(scaleX, scaleY); // 选择最大的比例以适应 canvas
// 计算背景图绘制的尺寸
const drawWidth = bgWidth * scale;
const drawHeight = bgHeight * scale;
// 绘制背景图
textCtx.drawImage(bg, 0, 0, drawWidth, drawHeight);
},
drawQRCode(textCtx, tempQrcodePath) {
const qrWidth = 550; // 二维码宽度
const qrHeight = 550; // 二维码高度
const qrX = (textCanvas.width - qrWidth + 40) / 2; // 水平居中
const qrY = (textCanvas.height - qrHeight + 940) / 2; // 垂直居中
// 绘制二维码到背景图上
const qrImage = textCanvas.createImage();
qrImage.src = tempQrcodePath;
qrImage.onload = () => {
textCtx.drawImage(qrImage, qrX, qrY, qrWidth, qrHeight);
// 合成图像成功后隐藏二维码
this.setData({
qrcodeVisible: false
});
};
qrImage.onerror = () => {
console.error('二维码绘制失败');
};
},
// 长按保存
// 最终合成图像保存到临时路径
saveQrcode() {
wx.getSetting({
success: (res) => {
if (!res.authSetting['scope.writePhotosAlbum']) {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success: () => {
this.saveCanvasToAlbum();
},
fail: (err) => {
console.error('用户拒绝授权保存相册', err);
wx.showToast({
title: '未授权保存相册',
icon: 'none'
});
}
});
} else {
this.saveCanvasToAlbum();
}
}
});
},
saveCanvasToAlbum() {
wx.showLoading({
title: '正在保存图片...',
});
wx.canvasToTempFilePath({
canvas: textCanvas,
success: (finalRes) => {
wx.saveImageToPhotosAlbum({
filePath: finalRes.tempFilePath,
success: () => {
wx.hideLoading();
wx.showToast({
title: '保存成功',
});
},
fail: (err) => {
wx.hideLoading();
console.error('保存失败', err);
wx.showToast({
title: '保存失败',
icon: 'none'
});
},
});
},
fail: (err) => {
wx.hideLoading();
console.error('合成图像失败', err);
wx.showToast({
title: '合成图像失败',
icon: 'none'
});
},
});
}
});
引入文件