<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> - 发布:2025-12-11 13:39
- 更新:2025-12-17 17:08
- 阅读:90
产品分类: uniapp/App
PC开发环境操作系统: Windows
PC开发环境操作系统版本号: windows10
HBuilderX类型: 正式
HBuilderX版本号: 4.87
手机系统: Android
手机系统版本号: Android 13
手机厂商: 华为
手机机型: nova7
页面类型: vue
vue版本: vue2
打包方式: 云端
项目创建方式: HBuilderX
示例代码:
操作步骤:
我这段代码放在底部导航栏首页index里可以获取正常metrics.width,但放在底部导航栏我的页面同样代码获取metrics.width就异常,在页面也可以正常渲染该字体
我这段代码放在底部导航栏首页index里可以获取正常metrics.width,但放在底部导航栏我的页面同样代码获取metrics.width就异常,在页面也可以正常渲染该字体
预期结果:
metrics.width为78.62992858886719
metrics.width为78.62992858886719
实际结果:
metrics.width为125.1123046875
metrics.width为125.1123046875
bug描述:
canvas中的measureText相同的代码在不同的页面运行结果不一样
2 个回复
Ask小助手
该bug反馈内容基本完整但存在关键缺失:BUG描述未明确区分App与小程序平台特性,复现步骤过于简略(未说明两个页面的具体差异,如是否均为nvue页面、DPI设置等),代码示例中
loadFontFace方法存在未使用参数且未处理字体加载完成到测量的时间差问题。预期结果78.63与实际结果125.11差异显著,符合异常特征。经核查知识库:
问题核心在于:不同页面中字体加载完成时机与canvas上下文初始化存在竞争条件。当页面快速切换时,"我的"页面可能在字体完全生效前执行measureText,导致测量值异常(125.11接近系统默认字体宽度)。建议用户:
loadFontFace的success回调中添加setTimeout确保字体渲染完成DCloud_UNI_OttoJi - 日常回复 uni-app/x 问题,如果艾特我没看到,请主动私信
你这个页面不包含 canvas ,如果你认为这个 bug 和 loadfontface 有关系请改成简单代码加载,如果没有关系请移除相关逻辑。
要回复问题请先登录或注册
公告
更多>相关问题