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' }); }, }); } });
复制
引入文件