uni-app 小程序 canvas绘制文字无法及时响应最新数据并回显
uni-app 小程序 canvas绘制文字无法及时响应最新数据并回显
产品分类:
uniapp/小程序/微信
PC开发环境操作系统:
Windows
PC开发环境操作系统版本号:
Windows 10 专业版
HBuilderX类型:
正式
HBuilderX版本号:
4.29
第三方开发者工具版本号:
1.06.2409140 win32-x64
基础库版本号:
3.4.7
项目创建方式:
HBuilderX
示例代码:
// 开始绘制二维码 圆角
async created() {
this.SystemInfo = await this.getSystemInfo();
this.ewmImg = await this.getImageInfo(this.invitationCode);
this.bgImg = await this.getImageInfo(this.bgImgUrl);
this.xcxImg = await this.getImageInfo(this.xcxCode);
if (this.SystemInfo.errMsg == 'getSystemInfo:ok' && this.ewmImg.errMsg == 'getImageInfo:ok' && this
.bgImg.errMsg == 'getImageInfo:ok' && this.xcxImg.errMsg == 'getImageInfo:ok') {
//
uni.showLoading({
title: '绘制中...'
});
// canvas名称、背景图片、小程序二维码、头像、编号(目前没啥用)可以用来判断给那个变量赋值
await this.canvasDrawFn('inviteQrcode', this.bgImg.path, this.xcxImg.path, this.ewmImg.path, 1);
} else {
console.log('err')
}
},
// 绘制方法 这样可以减少更多相同的写法
canvasDrawFn(eventName, bgImg, xcxImg, ewmImg, code) {
try {
let that = this;
let bgX = 287; // 背景宽度
let bgY = 392; // 背景高度
// 防止他不是获取不到 canvas-id
var ctx = uni.createCanvasContext(eventName, this);
ctx.drawImage(bgImg, 0, 0, bgX, bgY);
const avatarSize = 46; // 头像的尺寸(假设是正方形)
const radius = avatarSize / 2; // 半径
// 背景图片的距离 / 2
const centerX = bgX / 2; // 圆形裁剪位置 X
const centerY = bgY / 2; // 圆形裁剪位置 Y
let newCenterX = (centerX - 2);
let newCenterY = (centerY - 64);
// 收入
ctx.setFillStyle('#fe3c39');
ctx.font = `bold 24px PingFangSC-Regular`;
const pleaseTextUiInfo = ctx.measureText(`收入${this.amount}元`);
console.log('多少', this.amount);
ctx.fillText(`收入${this.amount}元`, (bgX - pleaseTextUiInfo.width) / 2, (bgY - 180));
// 成功上榜
ctx.setFillStyle('#fe3c39');
ctx.font = `bold 16px PingFangSC-Regular`;
const pleaseTextUiInfo1 = ctx.measureText(`我成功上榜!`);
ctx.fillText(`我成功上榜!`, ((bgX - pleaseTextUiInfo1.width) / 2) + 7, (bgY - 150));
// 城市地区
ctx.setFillStyle('#75280f');
ctx.font = `16px PingFangSC-Regular`;
const pleaseTextUiInfo2 = ctx.measureText(`排名${this.regionName}城市第${this.ranking}名`);
ctx.fillText(`排名${this.regionName}城市第${this.ranking}名`, ((bgX - pleaseTextUiInfo2.width) / 2), (bgY -
125));
// 二维码
ctx.drawImage(xcxImg, (bgX - 110), (bgY - 110), 75, 75);
// 设置圆角头像
ctx.beginPath();
ctx.arc(newCenterX, newCenterY, radius, 0, 2 * Math.PI, false);
ctx.clip();
// 计算绘制位置,使头像居中
const avatarX = newCenterX - radius; // 头像左上角 X 坐标
const avatarY = newCenterY - radius; // 头像左上角 Y 坐标
ctx.drawImage(ewmImg, avatarX, avatarY, avatarSize, avatarSize);
setTimeout(() => {
ctx.draw(true, (ret) => {
uni.hideLoading();
uni.canvasToTempFilePath({
canvasId: eventName,
fileType: 'jpg',
success(res) {
// 里面用that 不要用this,要不然使用里面的东西不生效
console.log('绘制成功', res);
if (code == 1) {
that.tempPath = res.tempFilePath;
} else if (code == 2) {
that.newTempPath = res.tempFilePath;
}
},
complete(error) {
// 这也是成功
if (error.errMsg == 'canvasToTempFilePath:ok') {
if (code == 1) {
that.tempPath = error.tempFilePath;
} else if (code == 2) {
that.newTempPath = error.tempFilePath;
}
} else {
console.error('绘制图片报错:', error);
}
}
}, this); // 在子组件中 canvasToTempFilePath 要加一个this 仅限 小程序需要
});
}, 200);
} catch (e) {
//TODO handle the exception
}
},
操作步骤:
进入排行榜页面 默认是日榜,点击分享数据正常,然后在切换周榜或月榜,在点击分享,数据还是日榜的数据,打印是最新的数据
预期结果:
每次切换榜单的时候获取最新的数据进行展示分享,并下载
实际结果:
只有第一次点开后是正确的,往后文字都没有根据我传递的数据进行变更,只有头像变更了
bug描述:
在uniapp小程序中,使用canvas绘制文字的时候疑似缓存问题(又不太像)因为我只有文字被缓存了,头像是最新的,我在子组件进行绘制的时候父组件把所需的数据都传递到子组件中,子组件通过props接受都是最新的数据,第一次打开数据是正确的,但是关闭后切换数据,在打开canvas组件数据一直显示是第一次的数据
代码在APP中是正常的,只有在小程序会出现canvas文字没有改变的问题,然后头部切换都是在父组件完成的,只有点击分享会把通过组件的ref去掉子组件的方法,让他自己打开,并绘制数据展示
在uni-app中,使用canvas绘制文字时,如果遇到无法及时响应最新数据并回显的问题,通常是因为canvas的绘制操作是异步的,且绘制过程需要在特定的生命周期函数或事件回调中进行。为了确保canvas能够及时响应并绘制最新的数据,你可以通过以下方式优化代码:
-
使用
canvas.draw(false, callback)
确保绘制完成:在绘制完成后,通过回调函数确保最新的数据已经被绘制。 -
在数据更新时重新绘制:确保在数据变化时,能够触发canvas的重新绘制。
下面是一个简单的代码示例,展示如何在uni-app中使用canvas绘制文字,并确保其能够及时响应数据变化:
<template>
<view>
<canvas canvas-id="myCanvas" style="width: 300px; height: 200px;"></canvas>
<button @click="updateText">Update Text</button>
</view>
</template>
<script>
export default {
data() {
return {
text: 'Hello, uni-app!'
};
},
methods: {
drawCanvas() {
const ctx = uni.createCanvasContext('myCanvas');
ctx.setFontSize(20);
ctx.setFillStyle('black');
ctx.fillText(this.text, 50, 100);
ctx.draw(false, () => {
console.log('Canvas drawing completed');
});
},
updateText() {
this.text = 'New Text Updated!';
this.$nextTick(() => {
this.drawCanvas();
});
}
},
mounted() {
this.drawCanvas();
}
};
</script>
<style scoped>
/* 添加必要的样式 */
</style>
解释
-
模板部分:包含一个canvas元素和一个按钮,点击按钮会触发
updateText
方法。 -
脚本部分:
data
中定义了一个text
变量,用于存储要绘制的文字。drawCanvas
方法使用uni.createCanvasContext
获取canvas上下文,并设置字体大小、颜色,然后绘制文字。绘制完成后,通过回调函数输出绘制完成的消息。updateText
方法更新text
变量的值,并在$nextTick
中调用drawCanvas
方法重新绘制canvas,确保数据更新后canvas能立即响应。mounted
生命周期钩子中调用drawCanvas
进行初始绘制。
通过这种方式,可以确保canvas能够及时响应并显示最新的数据。