前言
- 最近整个antd在线换主题功能,结果发现官方居然没有这功能。只能一开始写死。后来研究了几种方法,记录一下。
方案一
- 换less
- 使用antd-theme-generator先生成less颜色变量,在index.html中使用less加载,在js中切换less变量。
- 请注意antd的位置,因为我这项目是lerna的所以位置跟一般的不太一样。
const path = require('path');
const { generateTheme } = require('antd-theme-generator');
const options = {
stylesDir: path.join(__dirname, '../src/styles'),
antDir: path.join(__dirname, '../../../node_modules/antd'),
varFile: path.join(__dirname, '../src/styles/variables.less'),
mainLessFile: path.join(__dirname, '../src/styles/index.less'),
themeVariables: [
'@primary-color',
'@secondary-color',
'@text-color',
'@text-color-secondary',
'@heading-color',
'@layout-body-background',
'@layout-header-background',
'@border-radius-base',
],
outputFilePath: path.join(__dirname, '../public/color.less'),
};
generateTheme(options)
.then((less) => {
console.log('Theme generated successfully');
})
.catch((error) => {
console.log('Error', error);
});
// variables.less
@import "~antd/lib/style/themes/default.less";
@primary-color: #1890ff;
- 使用node 生成color文件后,在index中加载他:
<link
rel="stylesheet/less"
type="text/css"
href="<%= context.config.publicPath + 'color.less'%>"
rel="external nofollow"
/>
<script>
window.less = {
async: false,
env: 'development',
javascriptEnabled: true
};
</script>
<script
type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/less.js/3.11.1/less.min.js"
></script>
const [theme, setTheme] = React.useState('default');
const setThemeColor = (theme: 'default' | 'dark') => {
if (theme === 'default') {
window.less.modifyVars({
'@primary-color': 'red !important',
'@border-color-base': '#E9EEF7 !important',
'@layout-body-background': '#f0f2f5 !important',
'@layout-header-background': '#fffffe !important',
'@component-background': '#fffffe !important',
'@text-color': 'fade(@black, 65%) !important',
'@title-color': '#333 !important',
'@table-header-bg': 'hsv(0, 0, 98%) !important',
'@ant-selected-color': 'rgba(0, 0, 0, 0.65) !important',
'@table-row-hover-bg': '#F0FDFF !important',
'@modal-heading-color': 'fade(#000, 85%) !important',
'@page-ellipsis-color': 'rgba(0, 0, 0, 0.25) !important',
'@empty-text-color': 'rgba(0, 0, 0, 0.25) !important',
'@date-last-next': 'rgba(0, 0, 0, 0.25) !important',
'@cursor-text-color': '#1f1f1f !important',
'@descriptions-title-color': 'rgba(0, 0, 0, 0.85) !important',
'@descriptions-label-bg-color': '#fafafa !important',
'@alarm-chart-bg-color': '#f2f6fa !important',
'@statistic-title-color': 'rgba(0, 0, 0, 0.45) !important',
'@dashboard-box-shadow': '0 1px 4px rgba(0, 0, 0, 0.15) !important',
});
} else {
window.less.modifyVars({
'@primary-color': 'black !important',
'@border-color-base': '#303030 !important',
'@layout-body-background': '#000001 !important',
'@layout-header-background': '#1f1f1f !important',
'@component-background': '#141414 !important',
'@text-color': 'rgba(255, 255, 255, 0.65) !important',
'@title-color': 'rgba(255, 255, 255, 0.85) !important',
'@table-header-bg': '#1d1d1d !important',
'@ant-selected-color': '#1f1f1f !important',
'@table-row-hover-bg': '#000001 !important',
'@modal-heading-color': 'fade(@white, 100%) !important',
'@page-ellipsis-color': 'rgba(255, 255, 255, 0.25) !important',
'@empty-text-color': 'rgba(255, 255, 255, 0.45) !important',
'@date-last-next': 'rgba(255, 255, 255, 0.25) !important',
'@cursor-text-color': '#fefefe !important',
'@descriptions-title-color': 'rgba(255, 255, 255, 0.85) !important',
'@descriptions-label-bg-color': '#101010 !important',
'@alarm-chart-bg-color': '#0d0905 !important',
'@statistic-title-color': 'rgba(255, 255, 255, 0.45) !important',
'@dashboard-box-shadow':
'0 1px 4px rgba(255, 255, 255, 0.4) !important',
});
}
};
- 就是这玩意的优先级很低,全部得加important覆盖。要么需要去除antd自动引入的样式。
方案二
- 使用css 变量替换
- 利用umi-plugin-antd-theme
- 由于我用的umi3,网上都是umi2的教程,踩了不少坑。
- 因为umi文档上说会自动检测插件,那么我打印umi plugin list --key时看见antd-theme插件的key是antdTheme,结果尼玛在umirc里配这个键直接报错。
- 后来看别人的发现就在config里建个theme.config.json即可:
{
"theme": [
{
"key": "normal",
"fileName": "normal.css",
"modifyVars": { }
},
{
"key": "dust",
"fileName": "dust.css",
"modifyVars": { "@primary-color": "#F5222D" }
},
{
"key": "volcano",
"fileName": "volcano.css",
"modifyVars": { "@primary-color": "#FA541C" }
},
{
"key": "sunset",
"fileName": "sunset.css",
"modifyVars": { "@primary-color": "#FAAD14" }
},
{
"key": "cyan",
"fileName": "cyan.css",
"modifyVars": { "@primary-color": "#13C2C2" }
},
{
"key": "green",
"fileName": "green.css",
"modifyVars": { "@primary-color": "#52C41A" }
},
{
"key": "geekblue",
"fileName": "geekblue.css",
"modifyVars": { "@primary-color": "#2F54EB" }
},
{
"key": "purple",
"fileName": "purple.css",
"modifyVars": { "@primary-color": "#722ED1" }
},
{
"key": "dark",
"fileName": "dark.css",
"theme": "dark",
"modifyVars": {
"@table-selected-row-bg": "#30303d !important",
"@menu-dark-bg": "#23232E",
"@menu-dark-submenu-bg": "#23232E"
}
},
{
"key": "dust",
"theme": "dark",
"fileName": "dark-dust.css",
"modifyVars": {
"@primary-color": "#F5222D",
"@table-selected-row-bg": "#30303d !important",
"@menu-dark-bg": "#23232E",
"@menu-dark-submenu-bg": "#23232E"
}
},
{
"key": "volcano",
"theme": "dark",
"fileName": "dark-volcano.css",
"modifyVars": {
"@primary-color": "#FA541C",
"@table-selected-row-bg": "#30303d !important",
"@menu-dark-bg": "#23232E",
"@menu-dark-submenu-bg": "#23232E"
}
},
{
"key": "sunset",
"theme": "dark",
"fileName": "dark-sunset.css",
"modifyVars": {
"@primary-color": "#FAAD14",
"@table-selected-row-bg": "#30303d !important",
"@menu-dark-bg": "#23232E",
"@menu-dark-submenu-bg": "#23232E"
}
},
{
"key": "cyan",
"theme": "dark",
"fileName": "dark-cyan.css",
"modifyVars": {
"@primary-color": "#13C2C2",
"@table-selected-row-bg": "#30303d !important",
"@menu-dark-bg": "#23232E",
"@menu-dark-submenu-bg": "#23232E"
}
},
{
"key": "green",
"theme": "dark",
"fileName": "dark-green.css",
"modifyVars": {
"@primary-color": "#52C41A",
"@table-selected-row-bg": "#30303d !important",
"@menu-dark-bg": "#23232E",
"@menu-dark-submenu-bg": "#23232E"
}
},
{
"key": "geekblue",
"theme": "dark",
"fileName": "dark-geekblue.css",
"modifyVars": {
"@primary-color": "#2F54EB",
"@table-selected-row-bg": "#30303d !important",
"@menu-dark-bg": "#23232E",
"@menu-dark-submenu-bg": "#23232E"
}
},
{
"key": "purple",
"theme": "dark",
"fileName": "dark-purple.css",
"modifyVars": {
"@primary-color": "#722ED1",
"@table-selected-row-bg": "#30303d !important",
"@menu-dark-bg": "#23232E",
"@menu-dark-submenu-bg": "#23232E"
}
}
],
"min": true,
"isModule": true,
"ignoreAntd": false,
"ignoreProLayout": false,
"cache": true
}
import cssVars from 'css-vars-ponyfill';
export type ThemeType = keyof typeof THEME;
export const THEME = {
Light: {
'--font-high-emphasis': 'rgba(1, 8, 30, 1)',
'--font-primary': 'rgba(36, 174, 143, 1)',
},
Dark: {
'--font-high-emphasis': 'rgba(255, 255, 255, 1)',
'--font-primary': 'rgba(237, 110, 114, 1)',
},
};
export const setTheme = (themeKey: ThemeType) => {
const themeKeys = Object.keys(THEME);
let KEY: ThemeType;
if (themeKeys.includes(themeKey)) {
KEY = themeKey;
} else {
KEY = (localStorage.getItem('theme') as ThemeType | undefined) || 'Light';
}
localStorage.setItem('theme', KEY);
let styleLink = document.getElementById('theme-style') as HTMLLinkElement;
let hrefSrc = '/theme/normal.css';
if (KEY === 'Light') {
hrefSrc = '/theme/normal.css';
} else if (KEY === 'Dark') {
hrefSrc = '/theme/dark.css';
}
if (styleLink) {
styleLink.href = hrefSrc;
} else {
styleLink = document.createElement('link');
styleLink.type = 'text/css';
styleLink.rel = 'stylesheet';
styleLink.id = 'theme-style';
styleLink.href = hrefSrc;
document.body.append(styleLink);
}
cssVars({
onlyLegacy: false,
variables: THEME[KEY],
onError() {
cssVars({
onlyLegacy: false,
variables: THEME[KEY],
});
},
});
};
const setThemeColor = (theme: 'default' | 'dark') => {
if (theme === 'default') {
setTheme('Light');
} else {
setTheme('Dark');
}
};
- 部分变量会提示没有,请自己注入进去。
- 另外 “modifyVars” 不填或者填个空会导致
antd-pro-merge-less
插件报错或者在更新时,但不影响编译结果。