zoukankan      html  css  js  c++  java
  • 换肤功能(scss、css变量)

    博客地址:https://ainyi.com/104

    产品 SaaS 化,通常需要有换肤功能

    这里简单记录一下主题色及其衍生色(高亮、浅色)的更换功能

    scss 全局定义

    每个页面都有颜色,那么应该把颜色值定义在 global.scss 文件中,通过变量定义,比如

    $color-primary: #4762FE;
    $color-primary-dark: #3245D9;
    $color-primary-light: #C2D1FF;
    $color-primary-lightest: #EBF0FF;
    $color-primary-transparency: rgba(71,98,254,0.1);
    

    每个页面的样式表引入此文件

    @import './global.scss';
    
    // 使用例子
    .demo {
      color: $color-primary
    }
    

    这样,只要更改 scss 中全局变量的颜色值,就可以同步更改项目的颜色值

    css 变量定义

    思考如何注入颜色值?

    这里就用到 css 的变量函数了:var()
    之前有谈到使用 css 的变量以及赋值方法:Bilibili [冬] banner 早中晚切换效果

    var() 函数用于插入自定义的属性值

    两个参数:property,value
    property:必填,自定义属性的名称,必需以 -- 开头
    value:可选,备用值,在属性不存在的时候使用

    比如

    body {
      --tempColor: #fff;
    }
    .temp {
      color: var(--tempColor)
    }
    

    设置其属性:DOM.style.setProperty(name, value)


    这里就很清楚了,scss 中全局变量引入的是 var() 函数的变量值

    获取衍生色

    主题色是只有一个,需要通过主题色来获取其衍生颜色(高亮、浅色等)

    scss 中提供一个方法:mix()
    Mix 函数是将两种颜色根据一定的比例混合在一起,生成另一种颜色。其使用语法如下:

    mix($color-1,$color-2,$weight);
    

    $color-1 和 $color-2 指的是你需要合并的颜色,颜色可以是任何表达式,也可以是颜色变量
    $weight 为 合并的比例(选择权重),默认值为 50%,其取值范围是 0~1 之间。它是每个 RGB 的百分比来衡量,当然透明度也会有一定的权重
    如果指定的比例是 25%,意味着第一个颜色所占比例为 25%,第二个颜色所占比例为75%

    此外,scss 还有一个 HSL 函数,也是设置颜色值的方法,这里就不过多探究了


    坑来了
    当我把 var() 函数获取的颜色值放进 mix 函数中,居然报错:

    SassError: argument $color-2 of mix($color-1, $color-2, $weight: 50%) must be a color

    mix 函数无法使用带有 var() 函数变量的参数,HSL 函数也是;但普通变量是可以的


    最终只能使用 js 函数通过主题色来获取衍生颜色

    这里提供几个方法:

    // str: 十六进制颜色值,n:透明度
    export function colorRgba(str, n) {
      // 十六进制颜色值的正则表达式
      let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
      let sColor = str.toLowerCase()
      n = n || 1
      // 十六进制颜色转换为RGB格式
      if (sColor && reg.test(sColor)) {
        let sColorChange = getRgbNum(sColor)
        return 'rgba(' + sColorChange.join(',') + ',' + n + ')'
      } else {
        return sColor
      }
    }
    // 获取 rgb 颜色值
    function getRgbNum(sColor) {
      if (sColor.length === 4) {
        let sColorNew = '#'
        for (let i = 1; i < 4; i += 1) {
          // 补全颜色值 例如:#eee,#fff等
          sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
        }
        sColor = sColorNew
      }
      // 处理六位颜色值
      let sColorChange = []
      for (let i = 1; i < 7; i += 2) {
        // 核心代码,通过parseInt将十六进制转为十进制,parseInt只有一个参数时是默认转为十进制的,第二个参数则是指定转为对应进制
        sColorChange.push(parseInt('0x' + sColor.slice(i, i + 2)))
      }
      return sColorChange
    }
    // 加深或减弱颜色值
    export function lightDarkenColor(color, num) {
      let colorArr = getRgbNum(color)
      let sColorChange = []
      for (let i = 0; i < colorArr.length; i++) {
        let val = colorArr[i] + num
        if (val < 0) {
          val = 0
        }
        if (val > 255) {
          val = 255
        }
        sColorChange.push(val)
      }
      return 'rgba(' + sColorChange.join(',') + ',1)'
    }
    

    最后只需要在路由全局前置守卫中计算颜色值,并赋值到 css 变量上,在 scss 全局变量中用 var() 函数引入 css 变量(各种颜色值)

    换肤流程

    通过接口获取主题色 --> js 计算衍生色值 --> 赋值到 css 变量 --> scss 全局变量用 var() 函数引入 css 变量 --> 页面样式引用 scss 全局颜色值

    使用例子

    global.scss

    $color-primary: var(--primaryColor, #4762FE);
    $color-primary-dark: var(--primaryDarkColor, #3245D9);
    $color-primary-light: var(--primaryLightColor, #C2D1FF);
    $color-primary-lightest: var(--primaryLightestColor, #EBF0FF);
    $color-primary-transparency: var(--primaryTransparencyColor, rgba(71,98,254,0.1));
    

    路由守卫:

    router.beforeEach((to, from, next) => {
      const primaryColor = getConfigStyle() // 从接口获取的主题色
      const colorObj = {
        primaryColor: primaryColor,
        primaryDarkColor: lightDarkenColor(primaryColor, -20),
        primaryLightColor: colorRgba(primaryColor, 0.3),
        primaryLightestColor: colorRgba(primaryColor, 0.12),
        primaryTransparencyColor: colorRgba(primaryColor, 0.1)
      }
      Object.entries(colorObj).forEach(ele => {
        // 逐个设置 css 变量到 body 上
        document.body.style.setProperty(`--${ele[0]}`, ele[1])
      })
      next()
    })
    

    博客地址:https://ainyi.com/104

  • 相关阅读:
    centos 7 部署confluence
    在Ubuntu操作系统里安装Docker
    Python模块-pip
    微信小程序 等宽不等高瀑布流
    微信小程序 保存图片和复制文字 功能
    C# 模拟鼠标移动和点击
    使用Fiddler抓包工具更改请求的url请求参数
    C#中Request.ServerVariables详细说明及代理
    (C# webservice 获取客户端IP疑难杂症)---试过n种方法都失败,获取代理服务器,访问者客户端真实IP
    C# 命名管道中客户端访问服务器时,出现“对路径的访问被拒绝”
  • 原文地址:https://www.cnblogs.com/ainyi/p/14680298.html
Copyright © 2011-2022 走看看