uni-app老年模式字体设置

一、实现原理

借助插件,将项目中的字体单位rpx换成rem,结合官网提供的page-meta属性,通过控制根字体大小,达到调节字体大小的要求。

  1. emfont size of the element,是相对于父元素的字体大小单位;
  2. remfont size of the root element,是指相对于根元素的字体大小单位;
  3. page-meta:页面配置节点,用于指定页面的一些属性、监听页面事件,类似于html中的header标签,可以部分替代pages.json的功能。

二、实现步骤

1.1 安装第三方插件 postcss-px-to-viewport

npm install postcss-px-to-viewport --save-dev

1.2 项目根目录创建postcss.config.js,并写入配置

// postcss.config.js

const path = require('path')
module.exports = {
  parser: 'postcss-comment',
  plugins: {
    'postcss-import': {
      resolve(id, basedir, importOptions) {
        if (id.startsWith('~@/')) {
          return path.resolve(process.env.UNI_INPUT_DIR, id.substr(3))
        } else if (id.startsWith('@/')) {
          return path.resolve(process.env.UNI_INPUT_DIR, id.substr(2))
        } else if (id.startsWith('/') && !id.startsWith('//')) {
          return path.resolve(process.env.UNI_INPUT_DIR, id.substr(1))
        }
        return id
      }
    },
    'autoprefixer': {
      overrideBrowserslist: ["Android >= 4", "ios >= 8"],
      remove: process.env.UNI_PLATFORM !== 'h5'
    },
    // 借助postcss-px-to-viewport插件,实现rpx转px,文档:https://github.com/evrone/postcss-px-to-viewport/blob/master/README_CN.md
    // 以下配置,可以将rpx转换为1/2的px,如20rpx=10px,如果要调整比例,可以调整 viewportWidth 来实现
    'postcss-px-to-viewport': {
      unitToConvert: 'rpx', // 需要转换的单位
      viewportWidth: 750,
      unitPrecision: 5,
      propList: ['*'],
      fontViewportUnit: 'rem', // 字体需要转成的单位,只针对 font-size 属性
      selectorBlackList: [],
      minPixelValue: 1,
      mediaQuery: false,
      replace: true,
      exclude: undefined,
      include: undefined,
      landscape: false
    },
    '@dcloudio/vue-cli-plugin-uni/packages/postcss': {}
  }
}

1.3 根据页面设置,vuex取出设置大小

根据滑块来设置字体放大倍数,本文设置的是1-1.75倍,该放大倍数存储vuexstorage持久化存储中,当应用启动时先读取storage存储的放大倍数,设置到vuex中(如果没有则不设置)。

// App.vue文件
<script>
	export default {
		onLaunch: function() {
			const localFontScale = this.$storage.getLocalFontScale();
			if(localFontScale) { //如果有值的话要先设置一下
				this.$store.commit("setFontScale", localFontScale);
			}
		},
		onShow: function() {
			console.log('App Show')
		},
		onHide: function() {
			console.log('App Hide')
		}
	}
</script>

微信截图_20220419201417

该设置界面代码如下:

<template>
	<page-meta :root-font-size="`${baseFontSize}px`"></page-meta>
	<view id="font-scale">
		<view class="text-container" style="font-size:30rpx">拖动滑块以设置字体大小</view>
		
		<view class="slider-label-container">
			<view class="label-text" style="font-size:30rpx">标准</view>
			<view class="label-text" style="font-size:35rpx">中等</view>
			<view class="label-text" style="font-size:40rpx">较大</view>
			<view class="label-text" style="font-size:45rpx">特大</view>
		</view>
		<view class="slider-container">
			<slider
				min="1.0"
				max="1.75"
				:value="fontScale"
				@change="sliderChange"
				show-value
				step="0.25"
			/>
		</view>
		<view class="text-container" style="font-size:30rpx">标准字体大小:</view>
		<view class="text-container" style="font-size:30rpx">
			锦瑟无端五十弦,一弦一柱思华年。庄生晓梦迷蝴蝶,望帝春心托杜鹃。
			沧海月明珠有泪,蓝田日暖玉生烟。此情可待成追忆?只是当时已惘然。
		</view>
		<view class="text-container" style="font-size:30rpx">预览字体大小:</view>
		<view class="text-container preview-text">
			锦瑟无端五十弦,一弦一柱思华年。庄生晓梦迷蝴蝶,望帝春心托杜鹃。
			沧海月明珠有泪,蓝田日暖玉生烟。此情可待成追忆?只是当时已惘然。
		</view>
		
		<view class="btn-container" @click="onBtnFinishedClicked()">
			<view class="btn-confirm" hover-class="btn-press" hover-stay-time="250" style="font-size: 36rpx;">完成</view>
		</view>
	</view>
</template>

<script>
    import { TAB_BAR_HOME, TAB_BAR_ME } from '@/util/config.js';
    import { showModal } from '@/util/tips.js';

    export default {
        data() {
            return {
                fontScale: 1.0,
            };
        },
        onLoad() {
            //this.fontScale = this.$store.state.commonModule.$fontScale;
            this.fontScale = this.$store.getters.getFontScale;
            if(!this.fontScale) {
                this.fontScale = 1.0;
            }
        },
        computed: {
            baseFontSize() {
                return this.fontScale * 0.46;
            } 
        },
        methods: {
            sliderChange(e) {
                console.log('value 发生变化:' + e.detail.value);
                this.fontScale = e.detail.value;
            },
            onBtnFinishedClicked() {
                //如果修改了字体大小,则需要重新加载所有页面(因为已经加载的页面字体大小不会修改)
                showModal('确定修改字体大小?').then(res => {
                    if(res) {
                        this.$store.commit('setFontScale', this.fontScale);
                        this.$storage.setLocalFontScale(this.fontScale)
                        // 使用uni.reLaunch跳转到某个页面,并关闭所有页面
                        this.$Router.reLaunch(TAB_BAR_ME)
                    }
                })
            }
        }
    }
</script>

<style lang="scss" scoped>
#font-scale {
	width: 100%;
	height: 100%;
	box-sizing: border-box;
	background-color: $color_backgroud;
	padding-top: 24rpx;
	
	.slider-label-container {
		display: flex;
		box-sizing: border-box;
		align-items: center;
		padding: 16rpx 32rpx 0;
		
		.label-text {
			display: flex;
			align-items: center;
			flex: 1;
		}
	}
	
	.slider-container {
		padding: 0 32rpx 24rpx;
	}
	
	.text-container {
		padding: 12rpx 32rpx;
	}
	
	.preview-text {
		font-size: 30rem;
	}
	
	.btn-container {
		width: 100%;
		padding: 24rpx 32rpx 32rpx;
		box-sizing: border-box;
		
		.btn-confirm {
			display: flex;
			box-sizing: border-box;
			justify-content: center;
			align-items: center;
			padding: 20rpx 0;
			color: white;
			background-color: $color_primary;
			border-radius: 10rpx;
			font-weight: 400;
			
			&.btn-press {
				background-color: $color_primary_click;
			}
		}
	}
}
</style>

vuex代码如下:

import { getLocalFontScale } from '@/util/storage.js'

export default {
	state: {
		// 为了不和页面或组件的data中的造成混淆,state中的变量前面建议加上$符号
		//文字缩放倍数
		$fontScale: 1 
	},
	getters: {
		//获取缩放字体大小
		getScaleFontSize: state => {
			return state.$fontScale * 0.46; //基础单位字体大小设置为0.46
		},
		//获得字体缩放倍数
		getFontScale: state => {
			return state.$fontScale;
		}
	},
	mutations: {
		//设置
		setFontScale(state, fontScale) {
			state.$fontScale = fontScale;
		}
	},
	actions: {}
}

1.4 在每个页面中通过添加page-meta调节字体大小

page-meta配置项参考链接

<template>
    <page-meta :root-font-size="`${baseFontSize}px`"></page-meta>
    <view></view>
</template>

<script>
	export default {
		data() {
			return {
			};
		},
		computed: {
			baseFontSize() {
				return this.$store.getters.getScaleFontSize;
			} 
		}
	}
</script>

三、遇到的一些坑

3.1 某些手机输入框高度异常问题

动态设置字体因为设置了采用了page-meta属性,并使用了rem单位,导致在某些手机上输入框的高度坍塌,实际展现只有1-2个像素,此时需要设置输入框的css样式的固定高度,如果高度使用rem单位的话,在某些手机(如荣耀)上会导致输入框的高度过高,所以最终还是采用rpx来设置输入框的高度。

本文参考:

uniapp设置字体大小,老年模式
uniapp APP 老年人字体放大方案

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐