我也遇到了,在p70 pro 126系统,canvas 直接不能使用,纯白的
canvas组件绘图在纯鸿蒙系统不显示?苹果和华为手机非麒麟芯片<template> <view class="template-login "> <view class="tn-flex tn-flex-col-center tn-flex-row-center" style="margin-top: 200rpx;height: 100%;"> <canvas :canvas-id="canvasID" :style="{width:canvasWidth+'px',height:canvasHeight+'px'}"></canvas> <view v-if="qrCode == ''"> <QRCode ref="qrcode" /> </view> <!-- <button :disabled="canvasImages == '' ? false : true" type="primary" @click="createsShareImage">生成海报</button> --> <!-- #ifdef MP-WEIXIN --> <!-- <button type="warn" :disabled="qrCode != '' ? false : true" open-type="share">分享给朋友</button> --> <!-- #endif --> </view> <view class="tn-flex tn-flex-col-center tn-flex-row-center"> <button type="primary" :disabled="qrCode != '' ? false : true" @click="saveImg()">保存图片</button> </view> </view> </template> <script> import template_page_mixin from '@/libs/mixin/template_page_mixin.js' import QRCode from "@/libs/qr_code/qrcode.vue" var _this; export default { name: 'canvas-images', mixins: [template_page_mixin], props: { newPic: "", // canvasID 等同于 canvas-id canvasID: { Type: String, default: 'shareCanvas' }, canvasWidth: { // 画布宽度 Type: 'int', default: 375 }, canvasHeight: { // 画布高度 Type: 'int', default: 400 }, shareTitle: { // 分享标题 Type: 'String', default: '' }, goodsTitle: { // 商品宣传标题 Type: 'String', default: '' }, shareImage: { // 分享图片 Type: 'String', default: '../../static/bg2.png' }, qrSize: { // 二维码大小 Type: 'int', default: 200 }, qrUrl: { // 生成二维码的链接 Type: 'String', default: 'https://xxxxx?types=FK&url="login/login"' } }, components: { QRCode }, data() { return { qrCode: '', // 二维码 } }, mounted() { _this = this; }, onReady() { const dpr = wx.getSystemInfoSync().pixelRatio; console.log('dpr' + dpr) // 设置 Canvas 的实际宽高(如期望生成 200x200 的二维码) this.canvasWidth = 200 * dpr; this.canvasHeight = 200 * dpr; this.canvasCreate() }, methods: { // 生成分享图片 createsShareImage() { // console.log(this.$refs.canvas) this.$refs.canvas.canvasCreate(); }, // 回调图片地址 shareSuccess(e) { // console.log('地址',e) _this.qrCode = e }, // 分享 onShareAppMessage(res) { // if (res.from === 'button') { // console.log(res.target) // } console.log(_this.qrCode) return { title: '图片分享', path: _this.qrCode } }, // 创建二维码 canvasCreate() { let userId = uni.getStorageSync("userinfo").userId console.log(userId + "userId") _this.qrUrl = "https://xxxxxxx?type=FK&userId=" + userId _this.$refs.qrcode.make({ size: _this.qrSize, text: _this.qrUrl }) .then(res => { // 返回的res与uni.canvasToTempFilePath返回一致 // console.log(res) _this.qrCode = res.tempFilePath; _this.onCanvas(); }); }, // 画图 async onCanvas() { uni.showLoading({ title: "分享图片生成中..." }); const ctx = uni.createCanvasContext(_this.canvasID, _this); // 设置 canvas 背景色 ctx.setFillStyle('#FFFFFF'); ctx.fillRect(0, 0, _this.canvasWidth, _this.canvasHeight); ctx.setFillStyle('#FFFFFF'); // 背景图片 ctx.drawImage(_this.shareImage, 20, 20, 340, 370, ); ctx.setFontSize(18); ctx.setTextAlign('center'); ctx.fillText(_this.shareTitle, 375 / 2, 70); // 左边标题 ctx.setFillStyle('#3D7EFF'); ctx.setTextAlign('left') ctx.setFontSize(16) _this.writeTextOnCanvas(ctx, 28, 18, _this.goodsTitle, 120, 350); // 设置虚线 // ctx.setStrokeStyle('#333333'); // ctx.setLineDash([5, 10], 2); // ctx.beginPath(); // ctx.moveTo(220, 340); // ctx.lineTo(220, 420); // ctx.stroke(); // 二维码 ctx.drawImage(_this.qrCode, 70, 100, 230, 230); // ctx.draw(); // 延迟后渲染至canvas上 let pic = await _this.setTime(ctx) _this.$emit('success', pic); _this.qr_code = ''; }, /** * @param {Object} ctx_2d getContext("2d") 对象 * @param {int} lineheight 段落文本行高 * @param {int} bytelength 设置单字节文字一行内的数量 * @param {string} text 写入画面的段落文本 * @param {int} startleft 开始绘制文本的 x 坐标位置(相对于画布) * @param {int} starttop 开始绘制文本的 y 坐标位置(相对于画布) */ writeTextOnCanvas(ctx_2d, lineheight, bytelength, text, startleft, starttop) { // 获取字符串的真实长度(字节长度) function getTrueLength(str) { var len = str.length, truelen = 0; for (var x = 0; x < len; x++) { if (str.charCodeAt(x) > 128) { truelen += 2; } else { truelen += 1; } } return truelen; } // 按字节长度截取字符串,返回substr截取位置 function cutString(str, leng) { var len = str.length, tlen = len, nlen = 0; for (var x = 0; x < len; x++) { if (str.charCodeAt(x) > 128) { if (nlen + 2 < leng) { nlen += 2; } else { tlen = x; break; } } else { if (nlen + 1 < leng) { nlen += 1; } else { tlen = x; break; } } } return tlen; } for (var i = 1; getTrueLength(text) > 0; i++) { var tl = cutString(text, bytelength); ctx_2d.fillText(text.substr(0, tl).replace(/^\s+|\s+$/, ""), startleft, (i - 1) * lineheight + starttop); text = text.substr(tl); } }, // 彻底改成同步 防止拿到的图片地址为空 setTime(ctx) { return new Promise((resole, err) => { setTimeout(() => { ctx.draw(false, async () => { let pic = await _this.getNewPic(); _this.newPic = pic; console.log("pic==" + pic) resole(pic) }); }, 600) }) }, saveImg() { let url = _this.newPic; uni.getImageInfo({ src: url, success: (res) => { let path = res.path; uni.saveImageToPhotosAlbum({ filePath: path, success: (res) => { console.log(res); wx.showToast({ title: '已保存到相册', }) }, fail: (res) => { console.log(res); } }) }, fail: (res) => { console.log(res); } }) }, // 获取新的图片地址 getNewPic() { return new Promise((resolve, errs) => { setTimeout(() => { uni.canvasToTempFilePath({ canvasId: _this.canvasID, quality: 1, complete: (res) => { // 在H5平台下,tempFilePath 为 base64 // 关闭showLoading uni.hideLoading(); // 储存海报地址 也是分享的地址 resolve(res.tempFilePath) } }, _this); }, 200) }) }, }, mounted() { _this = this; }, // 点击左上角返回按钮时触发事件 goBack() { // 通过判断当前页面的页面栈信息,是否有上一页进行返回,如果没有则跳转到首页 const pages = getCurrentPages() if (pages && pages.length > 0) { const firstPage = pages[0] if (pages.length == 1 && (!firstPage.route || firstPage.route != 'pages/index')) { uni.reLaunch({ url: '/pages/index' }) } else { uni.navigateBack({ delta: 1 }) } } else { uni.reLaunch({ url: '/pages/index' }) } }, } </script> <style lang="scss" scoped> /* 胶囊*/ .tn-custom-nav-bar__back { width: 100%; height: 100%; position: relative; display: flex; justify-content: space-evenly; align-items: center; box-sizing: border-box; background-color: rgba(0, 0, 0, 0.15); border-radius: 1000rpx; border: 1rpx solid rgba(255, 255, 255, 0.5); color: #FFFFFF; font-size: 18px; .icon { display: block; flex: 1; margin: auto; text-align: center; } &:before { content: " "; width: 1rpx; height: 110%; position: absolute; top: 22.5%; left: 0; right: 0; margin: auto; transform: scale(0.5); transform-origin: 0 0; pointer-events: none; box-sizing: border-box; opacity: 0.7; background-color: #FFFFFF; } } </style>
02-27