收藏
回答

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>
回答关注问题邀请回答
收藏

2 个回答

  • 社区技术运营专员--Demons
    社区技术运营专员--Demons
    02-27

    请具体描述问题出现的流程,并提供能复现问题的简单代码片段(https://developers.weixin.qq.com/miniprogram/dev/devtools/minicode.html)。

    02-27
    有用
    回复 9
    • 苜蓿🐹
      苜蓿🐹
      02-27
      这个是苹果跟其他华为手机的
      02-27
      回复
    • 苜蓿🐹
      苜蓿🐹
      02-27
      这是鸿蒙手机的
      02-27
      回复
    • 苜蓿🐹
      苜蓿🐹
      02-27
      代码片段那个我创建不来,.问题中我已发该页面全部代码。业务逻辑就是进入该页面调用画布根据内容生成二维码,背景为本地图片
      02-27
      回复
    • 社区技术运营专员--Demons
      社区技术运营专员--Demons
      02-27回复苜蓿🐹
      你好,麻烦在手机微信那里上传下日志: 我->设置->帮助与反馈右上角有个上报日志的入口,麻烦提供一下微信号,时间点
      02-27
      回复
    • 苜蓿🐹
      苜蓿🐹
      02-27
      现在突然又好了,好神奇。
      02-27
      回复
    查看更多(4)
  • 花开富贵🧬
    花开富贵🧬
    02-27

    我也遇到了,在p70 pro 126系统,canvas 直接不能使用,纯白的

    02-27
    有用
    回复 1
    • 苜蓿🐹
      苜蓿🐹
      02-27
      你的解决了吗
      02-27
      回复
登录 后发表内容