1***@qq.com
1***@qq.com
  • 发布:2025-12-11 13:39
  • 更新:2025-12-17 17:08
  • 阅读:90

【报Bug】canvas中measureText的问题

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Windows

PC开发环境操作系统版本号: windows10

HBuilderX类型: 正式

HBuilderX版本号: 4.87

手机系统: Android

手机系统版本号: Android 13

手机厂商: 华为

手机机型: nova7

页面类型: vue

vue版本: vue2

打包方式: 云端

项目创建方式: HBuilderX

示例代码:
<template>  
<view @tap="ceshi">  
测试  
</view>  
</template>  

<script>  
export default {  
data() {  
return {  
measureContext: null  
}  
},  
created() {  
this.download()  
},  
methods: {  
ceshi(){  
uni.navigateTo({  
url:'/pages/index/tiao'  
})  
},  
async download() {  
// 下载字体文件  
const cachedPath = uni.getStorageSync(  
'https://write.quickoj.com/uploads/font_ttf/8320702d427f13b080819d668effc629.ttf ');  
console.log(cachedPath)  
if (cachedPath) {  
try {  
await this.loadFontFace(cachedPath)  
return  
} catch (e) {  
console.log('缓存字体加载失败,重新下载', e);  
uni.removeStorageSync(item.font_url); // 移除无效缓存  
}  
}  
console.log('下载')  
const tempPath = await this.downloadFontFile(  
'https://write.quickoj.com/uploads/font_ttf/8320702d427f13b080819d668effc629.ttf ');  
// 保存到本地(仅小程序/部分App支持)  
const savedPath = await this.saveFile(tempPath);  
uni.setStorageSync('https://write.quickoj.com/uploads/font_ttf/8320702d427f13b080819d668effc629.ttf ',  
savedPath);  
await this.loadFontFace(savedPath);  
},  
downloadFontFile(url) {  
return new Promise((resolve, reject) => {  
uni.downloadFile({  
url,  
success: (res) => {  
if (res.statusCode === 200) {  
resolve(res.tempFilePath);  
} else {  
reject(`下载失败,状态码:${res.statusCode}`);  
}  
},  
fail: reject,  
});  
});  
},  
saveFile(tempFilePath) {  
return new Promise((resolve, reject) => {  
uni.saveFile({  
tempFilePath,  
success: (res) => {  
resolve(res.savedFilePath); // 返回持久化路径  
},  
fail: reject,  
});  
});  
},  
loadFontFace(filePath, index, item) {  
const fontFamily = `customFont_1`;  
uni.loadFontFace({  
family: fontFamily,  
source: `url("${filePath}")`,  
success: () => {  
this.fontFamily = fontFamily  
this.createMeasureContext()  
// console.log(this.fontCache)  
},  
fail: (err) => {  
console.error(`字体加载失败,尝试回退网络地址:${item.font_url}`, err);  
}  
});  
},  
// 创建测量上下文的独立方法  
createMeasureContext() {  
try {  
// 创建测量上下文  
this.measureContext = uni.createCanvasContext('measureCanvas2', this);  
// 设置字体  
console.log('fontFamily', this.fontFamily)  
// const fontFamily = '"Noto Sans Thai", "Thonburi", "Tahoma", sans-serif';  
this.measureContext.font = `30px ${this.fontFamily || 'sans-serif'}`;  
console.log(this.measureContext)  
// 验证字体设置是否生效  
const testText = 'สวัสดีครับ';  
const metrics = this.measureContext.measureText(testText);  
console.log('测量上下文创建完成,测试文本宽度:', metrics.width);  
} catch (error) {  
console.error('创建测量上下文失败:', error);  
}  
},  
}  
}  
</script>  

<style lang="scss">  

</style>

操作步骤:

我这段代码放在底部导航栏首页index里可以获取正常metrics.width,但放在底部导航栏我的页面同样代码获取metrics.width就异常,在页面也可以正常渲染该字体

预期结果:

metrics.width为78.62992858886719

实际结果:

metrics.width为125.1123046875

bug描述:

canvas中的measureText相同的代码在不同的页面运行结果不一样

2025-12-11 13:39 负责人:DCloud_UNI_OttoJi 分享
已邀请:
Ask小助手

Ask小助手

该bug反馈内容基本完整但存在关键缺失:BUG描述未明确区分App与小程序平台特性,复现步骤过于简略(未说明两个页面的具体差异,如是否均为nvue页面、DPI设置等),代码示例中loadFontFace方法存在未使用参数且未处理字体加载完成到测量的时间差问题。预期结果78.63与实际结果125.11差异显著,符合异常特征。

经核查知识库:

  1. CanvasContext.measureText文档明确说明"App端2.8.12+支持同步接口",但用户HBuilderX 4.87版本低于最新修复版本(4.36.2024112612-alpha中修复了canvas相关渲染问题
  2. uni.loadFontFace平台差异指出Android平台需注意字体加载时序问题
  3. 用户使用Vue2+nvue场景,而知识库显示4.36版本修复了App-Android平台keepAlive组件切换问题,可能影响canvas上下文状态

问题核心在于:不同页面中字体加载完成时机与canvas上下文初始化存在竞争条件。当页面快速切换时,"我的"页面可能在字体完全生效前执行measureText,导致测量值异常(125.11接近系统默认字体宽度)。建议用户:

  1. 升级至HBuilderX 4.36+版本
  2. loadFontFace的success回调中添加setTimeout确保字体渲染完成
  3. 检查两个页面是否均为nvue页面(nvue对canvas有特殊限制)
  4. 参考font加载最佳实践使用字体加载完成检测机制
内容为 AI 生成,仅供参考
DCloud_UNI_OttoJi

DCloud_UNI_OttoJi - 日常回复 uni-app/x 问题,如果艾特我没看到,请主动私信

你这个页面不包含 canvas ,如果你认为这个 bug 和 loadfontface 有关系请改成简单代码加载,如果没有关系请移除相关逻辑。

要回复问题请先登录注册