内容简介:线上预览地址:看起来是不是还可以,如果你知道如何使用,相信你会更觉得我不是一个标题党。没错,就是这么简单,为了方便大家,我已经弄成了即插即用的组件~欢迎大家star + issue + pr。
线上预览地址: Dynamic-Antd-Theme-Demo
看起来是不是还可以,如果你知道如何使用,相信你会更觉得我不是一个标题党。
// 如何使用 import DynamicAntdTheme from 'dynamic-antd-theme'; render() { ... <DynamicAntdTheme /> ... } 复制代码
没错,就是这么简单,为了方便大家,我已经弄成了即插即用的组件~欢迎大家star + issue + pr。 dynamic-antd-theme
为什么要做ant-design的换肤方案
这里是我很想说的,我还没有自负到或者说贪心到有能力去实现一个完美的合理的antd动态换肤方案。比如开源社区里的 antd-theme-webpack-plugin 和 antd-theme-generator 就是很成熟的方案,利用webpack的方式在页面里通过引入less.js实现动态换肤,换的很彻底。
那么为什么我还要来搞一个所谓的动态换肤呢?理由如下:
- 首先,上面两个方案并不能覆盖所有的场景,他所需要的入口文件
index.html
,作为nextjs党的我,就怎么找也找不到,所以在我的nextjs脚手架项目里就没有配置成功。 - 其次,个人认为配置以及使用稍微繁琐以及额外引入太多内容。html文件必须引入less.js文件,因为这样才能使用window.less对主题进行动态更换。还有配置的时候各种css文件也是不太清楚意义。
- 最后,也是最重要的。有人在我的文章里提问了,也就是与 Next-Antd-Scaffold 这个脚手架相关的文章,感兴趣的可以去看看前面我写的文章。小伙伴没有配置成功,又没有思路,怎么办呢,作为热心作者,肯定要帮忙解决呀~
这里安利一波, Next-Antd-Scaffold 目前已经基本开发完成了,我个人也在用这个架子写项目,有很多小伙伴也在写项目,应该还可以,对Nextjs感兴趣的同学可以加入文章底部的微信群一起沟通哦~最主要的,你给我一个star,我尽心尽力尽我所能解决问题,:smile:
综上所述,个人花费了周末的时间,搞出来一个即插即用的antd换肤方案,一键安装直接使用。当然了,既然是这么简单,肯定也有弊端,毕竟我的主题是最简单的antd换肤方案而不是最完美的antd换肤方案,详细的听我娓娓道来。
实现过程
具体的实现过程,我将会从思路,解决方案、细节难点以及项目存在的弊端问题来进行说明。
这里我所有的例子都是通过 Next-Antd-Scaffold 来进行编写的~
思路
先来说思路,既然我想标新立异,最简单的antd的换肤方案,那肯定不能有复杂的配置过程以及表述不清的文档。当然,说实话,在没深读源码以及webpack机制之前,我还没有能力写出上面两个的那种水平的插件,哈哈:smile:。
所以,就只能另辟蹊径了。我的想法就是,能不能在系统运行过程中,通过类覆盖的方式来动态修改颜色,因为CSS加载机制是由上至下,同名会覆盖对应属性嘛,利用这个特性就来简单的尝试一下。
以button按钮为例,可以看到,我们设置的 @primaryColor = #524c1a
,类名是 .ant-btn-primary
,那么我们来进行覆盖。
// 样式变换代码 const styleDom = document.createElement('style'); styleDom.innerHTML = ` .ant-btn-primary { border-color: #0000ff; background-color: #0000ff; } `; document.getElementsByTagName('head')[0].appendChild(styleDom); 复制代码
可以看到,页面在未刷新的前提下,按钮实现了变色。因此,这个思路是可行的,接下来我们要考虑的就是细节问题了。
方案
通过上述实践,我们确定了思路,这里就来确定可行性方案。说实话,类名覆盖这种问题大部分前端开发应该都能想到,应该也有一部分人在用,毕竟换肤的需求是很多中后台系统的基本需求,不过即使是类名覆盖不同人也有不同的做法,而且类名覆盖的难点在于 —— 覆盖基础颜色还好,如果为每一个伪类元素如 :hover :active :focus
等都覆盖一个合适的color,不仅实现困难,而且工作量也很大。我这里想的就是,我来给大家实现一个类名覆盖的普适方案,你们再也不需要繁琐的一个页面一个页面去实现,或者各种修改css文件,只需要引入这个插件,自动把所有的类都覆盖好。
具体实现过程
-
提取antd的所有color相关类
我把
antd-v3.19.0版本
的css文件下载到了本地,大概有2W+行代码,从中我细心耐心的提取了所有@primaryColor
相关颜色(包括:hover :focus :active
)等。因为只保留了类下的color相关属性,所以精简到了900行代码左右。这里就简单截图,不给大家展示了,想看的话地址在这 theme.css 。
这里重点说明的是,
:root{ ... }
下面的几个colorVar,这也算是设计方案吧,因为这样,我只需要获取用户设置的颜色,然后生成相关颜色替换colorVar变量即可。不然的话我需要写一个正则,匹配所有的color,效率肯定没这个好 -
动态获取用户颜色,然后进行替换
这里其实很简单,就是改造我们要插入的style标签内容,具体代码如下:
const cssVar = ` :root { --primary-color: ${primaryColor}; --primary-hover-color: ${hoverColor}; --primary-active-color: ${activeColor}; --primary-shadow-color: ${shadowColor}; } `; // 给插入的标签赋id,避免多次插入<style> let styleNode = document.getElementById('dynamic_antd_theme_custom_style'); if (!styleNode) { // avoid repeat insertion styleNode = document.createElement('style'); styleNode.id = 'dynamic_antd_theme_custom_style'; styleNode.innerHTML = `${cssVar}\n${cssContent}`; document.getElementsByTagName('head')[0].appendChild(styleNode); } else { styleNode.innerHTML = `${cssVar}\n${cssContent}`; } 复制代码
上面的标签内容是:
<style>${cssVar}\n${cssContent}</style>
,cssVar
是我们定义的颜色相关的几个变量,然后cssContent
就是我提取的所有css代码toString()
一下成为字符串变量。动态获取颜色这一块,我使用的是
react-color
这个插件,然后既然是换肤,肯定应该保存用户选择方案,所以搭配的就是localStorage
进行客户端缓存,最后效果就是这样:
有人可能说了,你说了半天 @primaryColor
相关颜色,到现在还是只有一个 @primaryColor
,是不是在这扯犊子呢,:smile:别急,我都说了是最重要的地方,肯定是放在难点里了。
难点
这里值得跟大家分享一下,难点并不是从两万多行代码里抽离出所有与 @primaryColor
相关的属性,而是你需要通过选中的 @primaryColor
来动态生成浅颜色的 @primaryHoverColor
和深颜色的 @primaryActiveColor
。
这里使用过的人应该都明白我的意思,antd的button按钮,a标签等等, :hover/:focus/:active/:visited
等等这些属性都拥有自己的颜色,一些是与 @primaryColor
相比更浅,一些是与 @primaryColor
相比更深~具体看下面的动图,hover的时候颜色更浅一些,active的时候颜色更深一些
你不能单纯的把所有颜色相关属性统一变成一个颜色,虽然那样很简单,但是从体验上来讲就失去了一些用户体验感,那样的话还不如不做换肤了。所以接下来就详细说一下这块的实现过程。
去看antd的源码可以发现,他其实并没有相关 :hover :active :focus
颜色的详细设置,而是所有颜色都是通过 @primaryColor
转换而来的。
可以看到,它将 @primaryColor
分成了是个颜色级别,以 level6
作为分界线, <6
的颜色会相比 @primaryColor
浅一些,适合 :hover
这种, >6
的颜色会比 @primaryColor
深一些,适合 :active
这种。所有颜色都是通过 colorPalette
这个方法进行生成的,所以我们详细要说的就是这一块。
事先声明以及甩锅,我尽力去理解去尝试了,不过最后我实现的也只是简单的四种颜色,并没有像原来那样分成10个级别,不喜勿喷,欢迎感兴趣的提PR,弄的越来越好~
/** * 下面这些代码谨代表我个人的事先过程以及能力水平 * 我没仔细看官方实现,所以antd肯实现的更高级 **/ // 获取hover的浅颜色 function getHoverColor (color, index = 5) { return tinycolor.mix( '#ffffff', color, currentEasing(index) * 100 / primaryEasing ).toHexString(); } // 获取active的深颜色 function getActiveColor (color, index = 7) { return tinycolor.mix( '#333333', color, (1 - (currentEasing(index) - primaryEasing) / (1 - primaryEasing)) * 100 ).toHexString(); } 复制代码
上面有两个函数,一个是获取浅颜色,一个是获取深颜色。两个函数内部调用的都是一个叫做 tinycolor.mix
的方法,并且我们看一下参数就非常容易理解了,这个 mix
方法其实就是让我们的主色 @primaryColor
跟另一个颜色去融合,比如跟 #ffffff
去融合,即使我不懂代码不懂计算机,学过画画的应该也都知道,如果有颜色的跟白色的混合,颜色会变浅,但是不会变成其他色系,也就是 蓝色 -> 浅蓝色,红色 -> 浅红色
等等,另一个也同理,跟 #000000
等黑灰色系融合,就会加深。接下来就看这个 mix函数了
:
/* tinycolor-mix */ tinycolor.mix = function(color1, color2, amount) { amount = (amount === 0) ? 0 : (amount || 50); var rgb1 = tinycolor(color1).toRgb(); var rgb2 = tinycolor(color2).toRgb(); var p = amount / 100; var rgba = { r: ((rgb2.r - rgb1.r) * p) + rgb1.r, g: ((rgb2.g - rgb1.g) * p) + rgb1.g, b: ((rgb2.b - rgb1.b) * p) + rgb1.b, a: ((rgb2.a - rgb1.a) * p) + rgb1.a }; return tinycolor(rgba); }; 复制代码
这里就是将两个颜色和一个权重输入进去,最后输出一个rgba的颜色值。这里面的 tinycolor 是一个颜色相关的插件,感兴趣的可以去看看。
ok,然后那个权重又是什么东西啊,这里说实话我数学不是很好,就真看不懂了,反正他是一个贝叶斯曲线,就是为了让我们的颜色变换的更平滑~其他文章的解释大概也就是这样了,还有个图片:
这里更加深入的我就不说了,也说不明白,反正我是照猫画虎画出来的。需要强调一下的是曲线需要选中一个基线,antd的基线是如下:
/* basic-easiing */ const baseEasing = BezierEasing(0.26, 0.09, 0.37, 0.18); // 主色基线 const primaryEasing = baseEasing(0.6); // 融合颜色的基线 const currentEasing = index => baseEasing(index * 0.1); 复制代码
也不知道我讲没讲清楚,上述繁杂的一系列操作过后,你就能根据你输入的主色生成对应的相关主色系颜色值,然后进行cssVar替换即可~
其他特性
你可以通过如下方式进行直接使用:
npm install dynamic-antd-theme or yarn add dynamic-antd-theme 复制代码
组件可设置属性如下:
组件使用起来确实称得上史上最简单了,最后的效果说实话也超出了我最初的想法,真的还挺不错的。
弊端和遗留问题
@primaryColor <style>
总结
有的人看完可能觉得没什么技术含量,就是做了很多重复大量的css操作来覆盖类名而已,说实话,我也承认,但是我觉得有一句名言说的好: 这个世界上本没有路,走的人多了,就变成了路。
这个方案也同样如此,每个人都愿意在自己的项目里进行大量的复杂类替换,却不愿意嫌麻烦去弄一套通用antd覆盖类文件,而我只是愿意把路给大家走出来,仅此而已。并不是有什么技术含量的插件,我也承认,哈哈:smile:。
另外,希望大家能多给star,多提issue,为什么呢,因为想做好的话一个人肯定是能力有限的,不可能把所有组件所有场景都是适配好,如果大家在使用的时候能告诉我哪个版本那个组件效果不对了,我可以及时的修改上线。另外如果感兴趣,也可以多提pr,一起维护。当前版本支持 antd version <= 3.19.0的绝大多数组件效果。
如有问题,及时联系,谢谢:pray:。点star不迷路 dynamic-antd-theme
Next.js小交流群地址:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 10 种跨域解决方案(附终极方案)
- React 服务端渲染方案完美的解决方案
- Hadoop小文件解决方案-基于文件整合的解决方案
- 关于当前公开的组件化方案存在的问题与解决方案探索
- iOS 关于全面屏适配的方案及UI在不同尺寸下适配方案
- iOS 关于全面屏适配的方案及UI在不同尺寸下适配方案
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Fluent Python
Luciano Ramalho / O'Reilly Media / 2015-8-20 / USD 39.99
Learn how to write idiomatic, effective Python code by leveraging its best features. Python's simplicity quickly lets you become productive with it, but this often means you aren’t using everything th......一起来看看 《Fluent Python》 这本书的介绍吧!