Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前端明暗风颜色切换 #3

Open
YoRenChen opened this issue May 25, 2021 · 0 comments
Open

前端明暗风颜色切换 #3

YoRenChen opened this issue May 25, 2021 · 0 comments

Comments

@YoRenChen
Copy link
Owner

YoRenChen commented May 25, 2021

前端明暗风颜色切换

前言

该章节对AntDesign颜色处理进行的源码探索与思考。
构建色系与UI统一性,就需要UI组件和UI颜色体系达到一致的系统
本文在于探讨中台系统中UI颜色结构和自构仿制品,源码处理方式请自行查询。

👉🏻 项目地址

本文探讨方向:

  1. AntDesign 颜色处理分析
  2. 构建颜色与明暗风切换的系统

【目录大致流程】

  • AntDesign 颜色系统分析
  • 代码实现

AntDesign 颜色系统

该章节对AntDesign颜色构思
源码探究基于AntDesign-Vue(v1.6x)上进行。
该体系内居于 Less + HSV,函数式处理颜色分类和使用HSV进行明暗度置换。本质上更利于处理颜色关系上的耦合。

主色系构建

AntDesign 定义主色为@primary-color 。用 HSV 模型的值进行递减/递增得到完整渐变色板,构建主色对应的衍生色。
image-20210319-024543
衍生色主要根据以i=6的主色进行换算出10个:

# ant-design-vue/components/style/color/colorPalette.less
# 函数 colorPalette

# ant-design-vue/components/style/color/default.less
@color-5: color(~`colorPalette('@{color-6}', 5, '@{theme}')`);

根据颜色值、色号与主色色号(6)差的绝对值、减淡/加深这三个参数获取渐变后的色值,其中 HSV 的三个值分别经过了渐变调整:

// 获取色相渐变
# ant-design-vue/components/style/color/colorPalette.less
# 函数 getHue

var hueStep=2;
if (hsv.h >=60 && hsv.h <=240) {
   hue=isLight ? hsv.h - hueStep * i : hsv.h + hueStep * i;
}else {
   hue=isLight ? hsv.h + hueStep * i : hsv.h - hueStep * i;
}

泛色的应用场景包括:关键行动点,操作状态、重要信息高亮,图形化等场景。
image-20210319-024644

暗黑风格

在3.0版本中,antd-vue使用暗黑风格LESS文件覆盖default.less样式实现。
在antd4.0中对暗黑颜色配套自己的规则,调节色值和HSV中的V百分比。

image-20210319-024849

# ant-design-vue/components/style/themes/dark.less

@component-background: #141414;
@primary-6: @primary-color;
@primary-1: mix(color(~`colorPalette('@{primary-color}', 8) `), @component-background, 15%);

参考:

  1. ant-d-vue: components/style/themes/dark.less
  2. https://zhuanlan.zhihu.com/p/112470365
  3. Ant Design 色板生成算法演进之路

构建颜色转换

【 项目地址 】

构建步骤:

  1. 泛色与暗黑风泛色定义
  2. 构建思路分析
  3. Less文件与组件的构建

泛色与暗黑风泛色定义

本次构建参考并基于 Ant Design 使用的定义变量与泛色方案。

// 变量定义
# ant-design-vue/components/style/themes/default.less
# ant-design-vue/components/style/themes/dark.less

// 泛色处理
# ant-design-vue/components/style/color/colorPalette.less

// 颜色方法
# ant-design-vue/components/style/color/colorPalette/tinyColor.less

注意:因为上面代码在Less中定义函数,故Less配置中需要加入javascriptEnabled:true来处理函数

构建思路

  1. 在ant-design-vue Pro网站上进行的颜色切换的发现,当构建新的颜色时会替换Style标签
  2. 使用Less变量,通过变量把组件颜色关联起来
  3. 通过Less的modifyVars属性可以修改到Less的变量
  4. Less文件最终合并成为区分明(default)和暗(dark)风格的样式文件

【坑点】

  1. 不使用css自定义控制变量,因为在系统对泛色校对时使用Less的Color方法,无法支持复杂表达式:mix(var(--primary-color), #fff, 10%)。
  2. 由于运行时less-loader会先对less转换为css/wxss,此时成为标准CSS样色文件,变量被引用成为实际数值,不可以通过Less的modifyVars属性进行修改。

Less文件与组件的构建

styles 文件
├── styles
│   ├── color (颜色处理)
│   │   ├── colorPalette.less
│   │   └── tinyColor.less
│   ├── component (组件定义)
│   │   ├── button.less
│   │   ├── layout.less
│   │   └── menu.less
│   ├── dark.less (暗系)
│   └── default.less (明系)
组件区分

在定义一个组件的时候,我们可以区分开颜色与其他属性。例如我们定义一个Button时,区分出颜色系的属性,定义颜色组件styles,最终合并到default.less中,而暗系颜色则是在default基础上颜色覆盖。

image-20210319-025434

@unit-prefix: unit;

# styles button.less
@import '../default.less';
.@{unit-prefix}-btn {
  color: @text-color;
  &-switch {
    background-color: @disabled-color;
    &-checked {
      background-color: @color-6;
    }
  }
}

# button.vue
<div class="unit-btn">
  <button
    :class="{'unit-btn-switch-checked': checked}"
    type="button"
    class="unit-btn-switch"
  />
</div>

# button.less
.unit-btn-switch {
  font-size: 14px;
  ...
}
Less文件放置与引用

由于less-loader会在项目里自动处理,那我们需要把这类less合并到public文件夹中,在使用的时候直接创建link进行引用,在颜色切换的时候只需要跟新public的less文件即可实现。

Less处理

生成less文件存放到public里.js (👈点击查看实现代码)

  1. 遍历styles里的default.less和dark.less,把两份文件的内容与引入内容都导出来,经过css压缩分别成为2份文件
  2. 使用fs.writeFileSync把这两份文件写到public文件夹中
  3. 把执行上面2步骤的js放到webpack中执行,预先生成文件

【注意】
此时我们使用的是在html里引入less,所以我们还需要在html里引入less.js,它的作用是把linkrel="stylesheet/less"的less文件转成css,才能给到元素使用。

image-20210319-025635

颜色变化时候的切换.js (👈点击查看实现代码)

  1. 初始化的时候只需要引用public的less文件
  2. 颜色跟新与明暗风切换时,只需要通过修改less的modifyVars即可刷新public里的less变量。明暗风切换除了修改变量时也需要切换项目中less的引用link的href由default.less变为dark.less

【初步效果】
Mar-16-2021 09-56-59

看到效果真让人兴奋,正让人感到就要功成名就的时候,发现一个问题。
使用less作为一个样色切换有一个好处,可以直接通过less的modifyVars进行颜色切换。不过有个致命缺点,就是解析,网页刚进入的时候,由于less文件解析和css重绘会导致“卡色”。

Mar-18-2021 20-18-34

下图为Perfomance截图:
image-20210319-030346
(这说卡炸了不过分吧)

优化

引用less的优缺点明显,那么在看Pro的官网,发现是跟新的是CSS文件。
好家伙,使用CSS能解决解析的步骤。

  1. 在Less合并之后使用 Less 的 render + less-plugin-npm-import 转成 css ,并输出
  2. “颜色变化时候的切换.js”把less改为css
    ... ...
    :"不能使用modifyVars在不重新生成less的情况下进行修改确实绕路"
    :“没问题,我们只要重新获取到less内容打包”
    :“或者先把les是打包下来再使用modifyVars修改之后转CSS替换之前的CSS文件不就行了吗?”
    思路挺不错,不过就是浏览器环境里不能使用fs的文件操作...

等等!实际上在antDesign官网中,最新加载的只有一份样色CSS,而在切换颜色之后,就多加载了一份样式Less和less.js,实现了切换。
“:那么我想应该是一开始打包了Less资源和原始CSS文件,先加载的是CSS,后面切换颜色的时候再塞less文件和less.js”
再试一下... ...

同时打包出明暗风less文件和基础的样式CSS之后的效果:

【网站效果】
Mar-19-2021 10-14-35

再看一下Perfomance:
image-20210319-030541

这样一来初步达成想要的效果 🎉🎉🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant