|
|
@@ -1,14 +1,29 @@
|
|
|
+/**
|
|
|
+ * 小程序字体缩放适配
|
|
|
+ *
|
|
|
+ * 字号来源优先级:用户手动设置 > 微信系统字号(fontSizeScaleFactor / fontSizeSetting)> 1(默认)
|
|
|
+ * 值域钳制在 [0.9, 1.7],超出视为无效值按默认处理。
|
|
|
+ *
|
|
|
+ * 平台差异说明(微信体系,基于 uni.getAppBaseInfo()):
|
|
|
+ * - fontSizeScaleFactor:缩放比例(直接可用)
|
|
|
+ * - fontSizeSetting:用户设置的字号 px 值(基准 16px),需基础库 2.23.4+
|
|
|
+ * - rpx 不随字号变化,需手动乘系数才能让正文跟随用户设置
|
|
|
+ */
|
|
|
+
|
|
|
+// --- 读取微信系统字号系数(单次调用) ---
|
|
|
export function readSystemFontScale() {
|
|
|
try {
|
|
|
if (typeof uni !== 'undefined' && uni.getAppBaseInfo) {
|
|
|
const baseInfo = uni.getAppBaseInfo()
|
|
|
- if (baseInfo && typeof baseInfo.fontSizeScaleFactor === 'number' && !isNaN(baseInfo.fontSizeScaleFactor)) {
|
|
|
- return baseInfo.fontSizeScaleFactor
|
|
|
- }
|
|
|
- if (baseInfo && typeof baseInfo.fontSizeSetting === 'number' && !isNaN(baseInfo.fontSizeSetting)) {
|
|
|
- const scale = baseInfo.fontSizeSetting / 16
|
|
|
- if (scale > 0) {
|
|
|
- return scale
|
|
|
+ if (baseInfo) {
|
|
|
+ // 优先:直接缩放比例(微信基础库 >= 2.23.4 支持)
|
|
|
+ if (typeof baseInfo.fontSizeScaleFactor === 'number' && !isNaN(baseInfo.fontSizeScaleFactor)) {
|
|
|
+ return baseInfo.fontSizeScaleFactor
|
|
|
+ }
|
|
|
+ // 降级:原始 px 值除以基准 16px
|
|
|
+ if (typeof baseInfo.fontSizeSetting === 'number' && !isNaN(baseInfo.fontSizeSetting)) {
|
|
|
+ const scale = baseInfo.fontSizeSetting / 16
|
|
|
+ if (scale > 0) return scale
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -18,13 +33,13 @@ export function readSystemFontScale() {
|
|
|
try {
|
|
|
if (typeof wx !== 'undefined' && wx.getAppBaseInfo) {
|
|
|
const baseInfo = wx.getAppBaseInfo()
|
|
|
- if (baseInfo && typeof baseInfo.fontSizeScaleFactor === 'number' && !isNaN(baseInfo.fontSizeScaleFactor)) {
|
|
|
- return baseInfo.fontSizeScaleFactor
|
|
|
- }
|
|
|
- if (baseInfo && typeof baseInfo.fontSizeSetting === 'number' && !isNaN(baseInfo.fontSizeSetting)) {
|
|
|
- const scale = baseInfo.fontSizeSetting / 16
|
|
|
- if (scale > 0) {
|
|
|
- return scale
|
|
|
+ if (baseInfo) {
|
|
|
+ if (typeof baseInfo.fontSizeScaleFactor === 'number' && !isNaN(baseInfo.fontSizeScaleFactor)) {
|
|
|
+ return baseInfo.fontSizeScaleFactor
|
|
|
+ }
|
|
|
+ if (typeof baseInfo.fontSizeSetting === 'number' && !isNaN(baseInfo.fontSizeSetting)) {
|
|
|
+ const scale = baseInfo.fontSizeSetting / 16
|
|
|
+ if (scale > 0) return scale
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -34,43 +49,83 @@ export function readSystemFontScale() {
|
|
|
return 1
|
|
|
}
|
|
|
|
|
|
+// --- 钳制系数到 [0.9, 1.7] 并返回保留两位小数的值 ---
|
|
|
+function clampAndRound(scale) {
|
|
|
+ if (typeof scale !== 'number' || isNaN(scale) || scale <= 0) return 1
|
|
|
+ if (scale < 0.9) scale = 0.9
|
|
|
+ if (scale > 1.7) scale = 1.7
|
|
|
+ return Math.round(scale * 100) / 100
|
|
|
+}
|
|
|
+
|
|
|
+// --- 读取用户手动设置的字号系数(storage 持久化) ---
|
|
|
+export function getUserFontScale() {
|
|
|
+ try {
|
|
|
+ const stored = uni.getStorageSync('userFontScale')
|
|
|
+ if (typeof stored === 'number' && !isNaN(stored) && stored > 0) {
|
|
|
+ return clampAndRound(stored)
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ // ignore
|
|
|
+ }
|
|
|
+ return null // null 表示未设置
|
|
|
+}
|
|
|
+
|
|
|
+// --- 写入用户手动设置的字号系数 ---
|
|
|
+export function setUserFontScale(scale) {
|
|
|
+ let s = clampAndRound(scale)
|
|
|
+ try {
|
|
|
+ uni.setStorageSync('userFontScale', s)
|
|
|
+ } catch (e) {
|
|
|
+ // ignore
|
|
|
+ }
|
|
|
+ return s
|
|
|
+}
|
|
|
+
|
|
|
+// --- 对外接口:读取当前生效字号系数 ---
|
|
|
export function getFontScale() {
|
|
|
+ // 优先用户设置
|
|
|
+ const user = getUserFontScale()
|
|
|
+ if (user !== null) return user
|
|
|
+ // 其次 storage 中的系统系数(上次同步留下的缓存)
|
|
|
try {
|
|
|
const stored = uni.getStorageSync('fontSizeScaleFactor')
|
|
|
if (typeof stored === 'number' && !isNaN(stored) && stored > 0) {
|
|
|
- let scale = stored
|
|
|
- if (scale < 0.9) scale = 0.9
|
|
|
- if (scale > 1.7) scale = 1.7
|
|
|
- const rounded = Math.round(scale * 100) / 100
|
|
|
- return rounded
|
|
|
+ return clampAndRound(stored)
|
|
|
}
|
|
|
} catch (e) {
|
|
|
// ignore
|
|
|
}
|
|
|
- const systemScale = readSystemFontScale()
|
|
|
- let scale = systemScale
|
|
|
- if (isNaN(scale) || scale <= 0) {
|
|
|
- scale = 1
|
|
|
- }
|
|
|
- if (scale < 0.9) scale = 0.9
|
|
|
- if (scale > 1.7) scale = 1.7
|
|
|
- const rounded = Math.round(scale * 100) / 100
|
|
|
- return rounded
|
|
|
+ // 最终:实时从系统读取
|
|
|
+ return clampAndRound(readSystemFontScale())
|
|
|
}
|
|
|
|
|
|
+// --- 同步(冷启动 / 每次回到前台)---
|
|
|
export function syncFontScale() {
|
|
|
const systemScale = readSystemFontScale()
|
|
|
- let scale = systemScale
|
|
|
- if (isNaN(scale) || scale <= 0) {
|
|
|
- scale = 1
|
|
|
- }
|
|
|
- if (scale < 0.9) scale = 0.9
|
|
|
- if (scale > 1.7) scale = 1.7
|
|
|
- const rounded = Math.round(scale * 100) / 100
|
|
|
+ const scale = clampAndRound(systemScale)
|
|
|
try {
|
|
|
- uni.setStorageSync('fontSizeScaleFactor', rounded)
|
|
|
+ // 仅在用户未手动设置时写入 storage,避免把系统值覆盖掉用户的自定义偏好
|
|
|
+ if (getUserFontScale() === null) {
|
|
|
+ uni.setStorageSync('fontSizeScaleFactor', scale)
|
|
|
+ }
|
|
|
} catch (e) {
|
|
|
// ignore
|
|
|
}
|
|
|
- return rounded
|
|
|
+ return scale
|
|
|
+}
|
|
|
+
|
|
|
+// --- 构建 mp-html 标签默认样式(用于 p/div/section/li/blockquote 等正文标签)
|
|
|
+// baseFontSize: 基准字号 rpx(推荐 28~32),例如文章/商品介绍正文用 32
|
|
|
+// scale: 当前生效字号系数(调用 getFontScale() 获取)
|
|
|
+// 返回 tagStyle 对象,可直接传给 <mp-html :tag-style="tagStyle">
|
|
|
+export function buildContentTagStyle(baseFontSize, scale) {
|
|
|
+ const s = typeof scale === 'number' ? scale : 1
|
|
|
+ const size = Math.round(baseFontSize * s)
|
|
|
+ return {
|
|
|
+ p: 'font-size:' + size + 'rpx;color:#444;line-height:1.8;',
|
|
|
+ div: 'font-size:' + size + 'rpx;color:#444;line-height:1.8;',
|
|
|
+ section: 'font-size:' + size + 'rpx;color:#444;line-height:1.8;',
|
|
|
+ li: 'font-size:' + size + 'rpx;color:#444;line-height:1.8;',
|
|
|
+ blockquote: 'font-size:' + size + 'rpx;color:#666;line-height:1.7;'
|
|
|
+ }
|
|
|
}
|