uni-app动态修改主题色的方法详解
虚乄 人气:0前言
老是碰到初版制作完成没多久,就整一出说什么要更改整个项目的色彩体系。真的是宝宝心里苦啊!
起初都是通过uni项目自带的uni.scss中定义,在替换页面上对应的css。以便于达到一次性修改整体布局的样式。
一.uni.scss 使用方式
在该文件里定义: $名字 :颜色值;
使用时需要在 style 节点上加上 lang=“scss”
<style lang="scss" scoped> .bg { height: 120px; width: 100%; background-color: $uni-color-primary; } </style>
该方法使用,适合单一颜色修改,一次修改全局统一。
二.暗黑主题
暗黑模式(Dark Mode),也被称为夜间模式或深色模式,是一种高对比度,或者反色模式的显示模式。是一种有利于在黑暗环境下观看手机的高对比度的模式。uni-app的暗黑模式,是帮助开发者完成自己应用的暗黑模式的一批配置和API。开发者可以参考本文实现自己应用的暗黑模式。
注:HBuilder X 3.6.9+ 支持 目前只支持深色和浅色
具体介绍看官网地址:uniapp.dcloud.net.cn/tutorial/da…
三.自定义主题配置
可自行定义多种主题配色,通过js动态修改导航栏等色彩。缺点在于,页面加载缓慢时前期会显示出原有的色彩。整体上不影响使用。
注:在APP 微信小程序 H5 都行
1.在根目录下新建 theme 文件夹
css-theme.scss
主题适配主要css
css-variate.scss
统一颜色值配置
cue-theme.js
vue 混入js
system-theme.js
自定义的相关配置
css-theme
主要为使用sass切换主题,百度一下大部分都是按照以下配置,这里不过多介绍
注:uni中使用时 建议这个scss 在 uni.scss 中 引入该scss
/* * @author: Jay * @description: 通过监听 css 变量切换主题色 * @createTime: 2022-12-13 11:29:00 * @introduce: 需要在 uni.scss 中 引入该scss */ //统一配置色彩 @import "./css-variate.scss"; /*---------------------方法一 使用css 控制变量 ---------------------------*/ /* 使用方法 .css-theme { width: 100%; @include text-color(); @include base-background(); @include border-color(); @include shadow-color(); } */ /* 白天主题 颜色集合 */ $day-theme:( bg-color:$day-bg, text-color:$day-text, border-color: $day-border, shadow-color:$day-shadow ); /* 夜间主题 颜色集合 */ $night-theme:( bg-color:$night-bg, text-color:$night-text, border-color: $night-border, shadow-color: $night-shadow ); /* 玉红主题 颜色集合 */ $jade-theme:( bg-color:$jade-bg, text-color:$jade-text, border-color: $jade-border, shadow-color: $jade-shadow ); //定义主题对象 $themes: ( day-theme: $day-theme, night-theme: $night-theme, jade-theme: $jade-theme ); // 生成主题背景色样式 @mixin base-background(){ @each $themename , $theme in $themes { &.#{$themename} { background-color: map-get($map: $theme, $key: bg-color); } } } // 生成主题字体色样式 @mixin text-color(){ @each $themename , $theme in $themes { &.#{$themename} { color: map-get($map: $theme, $key: text-color) !important; } } } // 生成主题边框色样式 @mixin border-color($opa: 1.0){ @each $themename , $theme in $themes { &.#{$themename} { border-color: rgba(map-get($map: $theme, $key: border-color), $opa) !important; } } } // 生成主题阴影 @mixin shadow-color(){ @each $themename , $theme in $themes { &.#{$themename} { box-shadow: 0 16rpx 32rpx rgba(map-get($map: $theme, $key: shadow-color), 0.4); } } } /*---------------------方法二 使用css 属性选择器 ---------------------------*/ /* 使用方法 <view class="padding-sm" :data-theme="cueTheme"> 暗黑模式-官方自带:(只支持 白天黑夜) </view> */ /* 白天主题 */ [data-theme='day-theme'] { background-color: $day-bg; color: $day-text; border-color: $day-border !important; shadow-color: $day-shadow; } /* 夜间主题 */ [data-theme='night-theme'] { background-color: $night-bg; color: $night-text; border-color: $night-border !important; shadow-color: $night-shadow; } /* 玉红主题 */ [data-theme='jade-theme'] { background-color: $jade-bg; color: $jade-text; border-color: $jade-border !important; shadow-color: $jade-shadow; }
uni.scss中引入
/* 主题相关颜色 */ @import './theme/css-theme.scss';
css-variate
主要为配置主题所需css 颜色值,方便统一修改。
/* 主题 统一配置色彩 */ //页面背景色 $page-bg:var(--page-bg,#FFFFFF); // 白天主题 $day-bg: #FFFFFF; $day-text: #333333; $day-border: #c8c7cc; $day-shadow: #c8c7cc; // 夜间主题 $night-bg: #292929; $night-text: #FFFFFF; $night-border: #c8c7cc; $night-shadow: #FFFFFF; // 玉红主题 $jade-bg: #c04851; $jade-text: #FFFFFF; $jade-border: #eea2a4; $jade-shadow: #f1939c; /* 需要在js 中使用的css 导出 APP 无法使用 h5 微信小程序有值 */ :export { dayBg: $day-bg; nightBg: $night-bg; jadeBg: $jade-bg; }
cue-theme
主要使用 混入 (mixin) ,方便与在页面中复用相同的功能。
该方法主要调用vuex的数据 和 system-theme 中的方法
注:需要在main.js 导入该js
/* * @author: Jay * @description: 监听主题变化 * @createTime: 2022-12-12 15:22:19 */ import system from '../theme/system-theme' import { mapMutations, mapGetters } from 'vuex' export default { install(Vue) { Vue.mixin({ onShow() { //修改导航栏 底部 tab system.setSystemTheme(this.cueTheme) //获取缓存 背景色 let bgColor = uni.getStorageSync('pageColor') || ''; if (bgColor) { this.getSystemBg(bgColor) } //获取缓存 主题名字 let themeType = uni.getStorageSync('themeType') || ''; if (themeType) { this.cueGetTheme(themeType) } // 监听主题状态变化 uni.onThemeChange((res) => { // console.log("监听主题状态变化", res.theme); //黑夜 if (res.theme == 'dark') { this.cueGetTheme('night-theme') } //白天 if (res.theme == 'light') { // 有多个主题时 判断 缓存是否为白色主题 let type = uni.getStorageSync('themeType'); if (type != 'day-theme') { this.cueGetTheme(type) } else { this.cueGetTheme('day-theme') } } }); }, computed: { // 获取vuex 主题参数 ...mapGetters({ cueTheme: 'theme/theme', pageBg: 'theme/pageColor', }), }, methods: { // 修改主题 ...mapMutations({ cueGetTheme: 'theme/GET_THEME', themeCache: 'theme/SET_THEME_CACHE', pageColorCache: 'theme/SET_PAGE_COLOR' }), // 设置 全局背景色 getSystemBg() { //从 主题列表 获取 页面颜色 let bgColor = system.systemThemeBg(this.cueTheme) // console.log(bgColor); //缓存 已设置 背景色 this.pageColorCache(bgColor) } } }) } }
main.js 导入
//监听主题变化 import theme from './theme/cue-theme.js' Vue.use(theme)
system-theme
主要用来放置一些需要重复使用的js。可根据需求自行添加
注: themeList 为系统主题列表参数相关配置,用于全局设置系统导航栏,底部tab颜色值的存放。
注:其中导入 css-variate.scss 在app 没有相关数据返回,h5,微信小程序则有数据返回。其他平台自行测试。
/* * @author: Jay * @description: 主题相关配置 * @createTime: 2022-12-12 17:45:09 */ /* variables APP 拿不到值 h5 微信小程序有值返回 */ import variables from './css-variate.scss' export default { /* 系统主题列表 */ themeList() { return [{ title: "白天", name: "day-theme", navBg: variables.dayBg, navBgApp: "#FFFFFF", tabBg: "", tabSeleText: "", tabText: "", }, { title: "黑夜", name: "night-theme", navBg: variables.nightBg, navBgApp: "#292929", tabBg: "", tabSeleText: "", tabText: "", }, { title: "玉红", name: "jade-theme", navBg: variables.jadeBg, navBgApp: "#c04851", tabBg: "", tabSeleText: "", tabText: "", }] }, //根据主题 返回背景色 systemThemeBg(name) { let color = '' this.themeList().map((item, index) => { if (item.name === name) { color = item.navBgApp } }) return color }, //根据主题 修改系统 导航栏 底部 tab setSystemTheme(name) { this.themeList().map((item, index) => { if (item.name === name) { // 设置页面导航条颜色 this.setNavigationColor(item.name, item.navBgApp) // 设置 tabBar 样式 this.setTabBarColor(item.tabBg, item.tabSeleText, item.tabText) } }) }, /* 设置页面导航条颜色 name 主题名字 该颜色值只支持2种 故判断对于白天 为 #000 其他均为 #FFF bgClor 背景色 可以随意修改 */ setNavigationColor(name, bgClor) { let navigationBar = { // 前景颜色值 仅支持 #ffffff 和 #000000 frontColor: name == 'day-theme' ? "#000000" : "#ffffff", // 背景颜色值 backgroundColor: bgClor || "#FFFFFF", // fail(err) { // console.error(err) // } } uni.setNavigationBarColor(navigationBar) }, /* 动态 设置 tabBar 样式 */ setTabBarColor(bgColor, seleColor, color) { let tabBar = { // 背景色 backgroundColor: bgColor || '#ffffff', // 文字选中时的颜色 selectedColor: seleColor || '#3cc51f', // 文字默认颜色 color: color || '#7A7E83', } uni.setTabBarStyle(tabBar) } }
2.vuex 配置
使用vuex模块化开发(module)用于区分主题相关设置 与其他需求。
theme.js 模块
注:namespaced: true 主要为 cue-theme 用于模块化调用。缺少这个,在调用cue-theme中的方法时,拿不到所需参数
//主题相关配置 import system from '../../theme/system-theme' const theme = { namespaced: true, state: { theme: "day-theme", //主题列表 theme: system.themeList(), //页面背景色 pageColor: "", }, mutations: { //设置主题色 GET_THEME(state, provider) { state.theme = provider //修改导航栏 底部 tab system.setSystemTheme(state.theme) }, //设置主题缓存 SET_THEME_CACHE(state, provider) { uni.setStorage({ key: 'themeType', data: provider }); }, //设置主题缓存 SET_PAGE_COLOR(state, provider) { state.pageColor = provider //缓存 uni.setStorage({ key: 'pageColor', data: provider }); }, }, getters: { theme: state => state.theme, pageColor: state => state.pageColor }, actions: { } } export default theme
index.js 全局导出
import Vue from "vue" import Vuex from "vuex" //登录 import logIn from "./modules/login.js" //主题切换 import theme from "./modules/theme.js" Vue.use(Vuex) const store = new Vuex.Store({ modules: { theme, logIn } }) export default store
main.js中导入
//引入 storeimport store from 'store/index.js' Vue.prototype.$store = store
3.页面中使用
class="conter" :style="{'--page-bg':pageBg}"
为该页面单独设置背景色 ,需要配合 page 设置页面高度使用
:data-theme="cueTheme"
给view设置data-theme属性,根据名字匹配对应颜色
:class="[cueTheme]"
设置对应的名字, css 中使用 @include text-color();
案例地址: gitee.com/jielov/uni-…
<!-- * @author: Jay * @description: 动态修改主题色 * @createTime: 2022-12-12 14:55:31 --> <template> <view class="conter" :style="{'--page-bg':pageBg}"> <view class="padding margin-bottom-xl css-theme" :class="[cueTheme]"> <view class="text-lg text-center text-bold"> 暗黑模式 </view> <view class="margin-top-sm" @click="openDoc"> uni-app的暗黑模式。<text class="text-blue">点击查看官方文档</text> </view> </view> <view class="css-theme padding" :class="[cueTheme]"> <view class="text-center text-bold text-lg"> 通过判断css 名字修改主题!!! </view> <view class="margin-tb-sm text-lg text-center"> 当前主题:{{cueTheme}} </view> <view class="margin-tb-sm text-lg text-center"> 当前页面背景色:{{pageBg}} </view> <view class="flex align-center justify-around"> <button class="cu-btn round" @click="cssEditThemeBut('day-theme')">白天</button> <button class="cu-btn round" @click="cssEditThemeBut('night-theme')">黑夜</button> <button class="cu-btn round" @click="cssEditThemeBut('jade-theme')">玉红</button> </view> </view> <view class="padding margin-top-xl" :data-theme="cueTheme"> <view class="text-center text-bold text-lg"> 通过 data-theme 判断 名字修改主题!!! </view> </view> </view> </template> <script> export default { data() { return { url: 'https://uniapp.dcloud.net.cn/tutorial/darkmode.html#open-darkmode' }; }, onLoad() { console.log("当前主题:", this.cueTheme); }, onShow() {}, methods: { cssEditThemeBut(e) { //修改主题 this.cueGetTheme(e) //设置主题缓存 this.themeCache(e) //设置 全局背景色 this.getSystemBg() // js自改变量值 h5 可用 // document.getElementsByTagName('body')[0].style.setProperty('--page-bg', 'red'); }, openDoc() { // #ifdef APP plus.runtime.openWeb(this.url); // #endif // #ifdef H5 let a = document.createElement('a'); a.href = this.url; a.target = '__blank'; a.click(); a = null; // #endif } } } </script> <style> /* 全局背景色 */ page { height: 100%; } </style> <style lang="scss" scoped> // 全局背景色 .conter { height: 100%; background-color: $page-bg; } .css-theme { // border: 2px solid; @include text-color(); @include base-background(); @include border-color(); @include shadow-color(); } </style>
四.黑夜 白天主题展示
总结
加载全部内容