内容简介:线上预览地址:看起来是不是还可以,如果你知道如何使用,相信你会更觉得我不是一个标题党。没错,就是这么简单,为了方便大家,我已经弄成了即插即用的组件~欢迎大家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在不同尺寸下适配方案
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
像计算机科学家一样思考Python
(美)Allen B.Downey / 赵普明 / 人民邮电出版社 / 2013-8 / 49
《像计算机科学家一样思考python》按照培养读者像计算机科学家一样的思维方式的思路来教授python语言编程。全书贯穿的主体是如何思考、设计、开发的方法,而具体的编程语言,只是提供一个具体场景方便介绍的媒介。《像计算机科学家一样思考python》并不是一本介绍语言的书,而是一本介绍编程思想的书。和其他编程设计语言书籍不同,它不拘泥于语言细节,而是尝试从初学者的角度出发,用生动的示例和丰富的练习来......一起来看看 《像计算机科学家一样思考Python》 这本书的介绍吧!