目录
- 前言
- 一.uni.scss 使用方式
- 二.暗黑主题
- 三.自定义主题配置
- 1.在根目录下新建 theme 文件夹
- css-theme
- uni.scss中引入
- css-variate
- cue-theme
- main.js 导入
- system-theme
- 2.vuex 配置
- index.js 全局导出
- main.js中导入
- 3.页面中使用
- 四.黑夜 白天主题展示
- 总结
前言
老是碰到初版制作完成没多久,就整一出说什么要更改整个项目的色彩体系。真的是宝宝心里苦啊!
起初都是通过uni项目自带的uni.scss中定义,在替换页面上对应的css。以便于达到一次性修改整体布局的样式。
一.uni.scss 使用方式
在该文件里定义: $名字 :颜色值;
使用时需要在 style 节点上加上 lang=“scss”
<style lang="scss" scoped> | |
.bg { | |
height:px; | |
width:%; | |
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:-12-13 11:29:00 | |
* @introduce: 需要在 uni.scss 中 引入该scss | |
*/ | |
//统一配置色彩 | |
"./css-variate.scss"; | |
/*---------------------方法一 使用css 控制变量 ---------------------------*/ | |
/* | |
使用方法 | |
.css-theme { | |
width:%; | |
@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 | |
); | |
// 生成主题背景色样式 | |
-background(){ | base|
$themename , $theme in $themes { | |
&.#{$themename} { | |
background-color: map-get($map: $theme, $key: bg-color); | |
} | |
} | |
} | |
// 生成主题字体色样式 | |
-color(){ | text|
$themename , $theme in $themes { | |
&.#{$themename} { | |
color: map-get($map: $theme, $key: text-color) !important; | |
} | |
} | |
} | |
// 生成主题边框色样式 | |
-color($opa:.0){ | border|
$themename , $theme in $themes { | |
&.#{$themename} { | |
border-color: rgba(map-get($map: $theme, $key: border-color), $opa) !important; | |
} | |
} | |
} | |
// 生成主题阴影 | |
-color(){ | shadow|
$themename , $theme in $themes { | |
&.#{$themename} { | |
box-shadow: 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: #; | |
$day-border: #cc7cc; | |
$day-shadow: #cc7cc; | |
// 夜间主题 | |
$night-bg: #; | |
$night-text: #FFFFFF; | |
$night-border: #cc7cc; | |
$night-shadow: #FFFFFF; | |
// 玉红主题 | |
$jade-bg: #c; | |
$jade-text: #FFFFFF; | |
$jade-border: #eeaa4; | |
$jade-shadow: #fc; | |
/* | |
需要在js 中使用的css 导出 | |
APP 无法使用 | |
h 微信小程序有值 | |
*/ | |
:export { | |
dayBg: $day-bg; | |
nightBg: $night-bg; | |
jadeBg: $jade-bg; | |
} |
cue-theme
主要使用 混入 (mixin) ,方便与在页面中复用相同的功能。
该方法主要调用vuex的数据 和 system-theme 中的方法
注:需要在main.js 导入该js
/* | |
* @author: Jay | |
* @description: 监听主题变化 | |
* @createTime:-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:-12-12 17:45:09 | |
*/ | |
/* | |
variables APP 拿不到值 | |
h 微信小程序有值返回 | |
*/ | |
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: "#", | |
tabBg: "", | |
tabSeleText: "", | |
tabText: "", | |
}, { | |
title: "玉红", | |
name: "jade-theme", | |
navBg: variables.jadeBg, | |
navBgApp: "#c", | |
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 主题名字 该颜色值只支持种 故判断对于白天 为 #000 其他均为 #FFF | |
bgClor 背景色 可以随意修改 | |
*/ | |
setNavigationColor(name, bgClor) { | |
let navigationBar = { | |
// 前景颜色值 仅支持 #ffffff 和 # | |
frontColor: name == 'day-theme' ? "#" : "#ffffff", | |
// 背景颜色值 | |
backgroundColor: bgClor || "#FFFFFF", | |
// fail(err) { | |
// console.error(err) | |
// } | |
} | |
uni.setNavigationBarColor(navigationBar) | |
}, | |
/* | |
动态 设置 tabBar 样式 | |
*/ | |
setTabBarColor(bgColor, seleColor, color) { | |
let tabBar = { | |
// 背景色 | |
backgroundColor: bgColor || '#ffffff', | |
// 文字选中时的颜色 | |
selectedColor: seleColor || '#cc51f', | |
// 文字默认颜色 | |
color: color || '#A7E83', | |
} | |
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:-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自改变量值 h 可用 | |
// document.getElementsByTagName('body')[].style.setProperty('--page-bg', 'red'); | |
}, | |
openDoc() { | |
// #ifdef APP | |
plus.runtime.openWeb(this.url); | |
// #endif | |
// #ifdef H | |
let a = document.createElement('a'); | |
a.href = this.url; | |
a.target = '__blank'; | |
a.click(); | |
a = null; | |
// #endif | |
} | |
} | |
} | |
</script> | |
<style> | |
/* 全局背景色 */ | |
page { | |
height:%; | |
} | |
</style> | |
<style lang="scss" scoped> | |
// 全局背景色 | |
.conter { | |
height:%; | |
background-color: $page-bg; | |
} | |
.css-theme { | |
// border:px solid; | |
@include text-color(); | |
@include base-background(); | |
@include border-color(); | |
@include shadow-color(); | |
} | |
</style> |