YoRenChen / Blog

web blog
MIT License
7 stars 1 forks source link

前端明暗风颜色切换 #3

Open YoRenChen opened 3 years ago

YoRenChen commented 3 years ago

前端明暗风颜色切换

前言

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

👉🏻 项目地址

本文探讨方向:

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

【目录大致流程】

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

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