elementPlus自定义主题色

自己真实项目代码。这些类名是基于elementPlus的,如果是其他UI框架可自行修改类名即可

import { unref } from "vue";
import { changeToRgb } from "@/libs";
import { appStore } from "@/stores/app/app";
import { storeToRefs } from "pinia";
const mixColor = "#ffffff";
const el = document.documentElement;
export const setTheme = () => {
  const app = appStore();
  const { themeColor, fillColor, gradientColor, colorStyle } = storeToRefs(app);

  const obj: any = {
    primary: unref(themeColor), //默认按钮颜色要随主色题变化
    info: unref(colorStyle).info,
    warning: unref(colorStyle).warning,
    danger: unref(colorStyle).danger,
    success: "#67c23a",
    error: "#f56c6c",
  };
  Object.keys(obj).forEach((key: string) => {
    _color(key, obj[key]);
  });
  _bg({
    gradientColor: gradientColor,
  });
  _border(colourBlend(themeColor.value, mixColor, 0.6));
  _fill(gradientColor);
  _text("#a39e9e");
};
const _color = (type: string, color: any) => {
  const body: any = document.querySelector("body");
  el.style.setProperty(`--el-color-${type}`, color);
  body.style.setProperty(`--van-${type}-color`, color);
  for (let i = 1; i < 10; i++) {
    el.style.setProperty(
      `--el-color-${type}-light-${i}`,
      colourBlend(color, mixColor, i / 10)
    );
    // 按钮点击elementPlus用dark主题的2号颜色。(特殊处理)
    el.style.setProperty(`--el-color-${type}-dark-2`, changeToRgb(color, 0.9));
  }
};

const _bg = (params: any) => {
  const { gradientColor } = params;
  // 穿梭框背景,下拉框(不需要给透明度)
  el.style.setProperty(
    "--el-bg-color-overlay",
    changeToRgb(gradientColor.value)
  );
  el.style.setProperty("--el-bg-color", changeToRgb(gradientColor.value));
  el.style.setProperty(
    "--el-disabled-bg-color",
    changeToRgb(gradientColor.value, 0.7)
  );
};

const _border = (color: any) => {
  el.style.setProperty("--el-border-color", color);
  const objSuffixs = ["light", "lighter", "extra-light"];
  objSuffixs.forEach((key: string, index: number) => {
    el.style.setProperty(
      `--el-border-color-${key}`,
      colourBlend(color, mixColor, (index + 1) / 10)
    );
  });

  // xx项目特殊处理
  el.style.setProperty(
    "--el-border-color-lighter",
    colourBlend("#2A598A", mixColor, 0)
  );
};

const _fill = (color: any) => {
  el.style.setProperty("--el-fill-color", unref(color));
  el.style.setProperty("--el-fill-color-blank", changeToRgb(unref(color), 0.4));
  const fillSuffixs = ["light", "lighter", "extra-light"];
  fillSuffixs.forEach((key: string, index: number) => {
    // el.style.setProperty(`--el-fill-color-${key}`, unref(color));
    el.style.setProperty(
      `--el-fill-color-${key}`,
      changeToRgb(
        colourBlend(unref(color), "#ffffff", (index + 1) / 10),
        1 - ((index + 1) * 2) / 10
      )
    );
  });

  // xx项目特殊处理
  el.style.setProperty(
    "--el-fill-color-light",
    colourBlend("#112C4D", "#ffffff", 0)
  );
};

const _text = (color: any) => {
  const app = appStore();
  const { themeColor } = storeToRefs(app);
  el.style.setProperty("--el-text-color-primary", "#ffffff");
  el.style.setProperty("--el-text-color-regular", "#ffffff");
  el.style.setProperty("--el-text-color-disabled", themeColor.value);
  const textSuffixs = ["secondary", "placeholder"];
  textSuffixs.forEach((key: string, index: number) => {
    el.style.setProperty(
      `--el-text-color-${key}`,
      colourBlend(color, mixColor, (index + 1) / 10)
    );
  });
};

//混合
const colourBlend = (c1: any, c2: any, ratio: any) => {
  ratio = Math.max(Math.min(Number(ratio), 1), 0);
  const r1 = parseInt(c1.substring(1, 3), 16);
  const g1 = parseInt(c1.substring(3, 5), 16);
  const b1 = parseInt(c1.substring(5, 7), 16);
  const r2 = parseInt(c2.substring(1, 3), 16);
  const g2 = parseInt(c2.substring(3, 5), 16);
  const b2 = parseInt(c2.substring(5, 7), 16);
  let r: any = Math.round(r1 * (1 - ratio) + r2 * ratio);
  let g: any = Math.round(g1 * (1 - ratio) + g2 * ratio);
  let b: any = Math.round(b1 * (1 - ratio) + b2 * ratio);
  r = ("0" + (r || 0).toString(16)).slice(-2);
  g = ("0" + (g || 0).toString(16)).slice(-2);
  b = ("0" + (b || 0).toString(16)).slice(-2);
  return "#" + r + g + b;
};

如果有几套主题色,思路如下:
setTheme(‘主题色’),内部再写几套枚举值来对应各种所需颜色。

你也可以设置自己组件风格和elementPlus风格统一,代码如下:

@use "sass:map";
@use "./var.scss" as *;

@mixin fourCombine($prefix, $type) {
  $fourName: $prefix + $type;
  .#{$fourName} {
    @content;
  }
}

// 四色图  danger warning info  primary
@each $linkType in $four {
  @include fourCombine("sc_four_", $linkType) {
    // color: map.get($four-colors, #{$linkType}, "base");
    background: map.get($four-colors, #{$linkType}, "base");
  }
}

// 所有颜色
@mixin colorCombine($prefix, $type) {
  $fourName: $prefix + $type;
  .#{$fourName} {
    @content;
  }
}

@each $linkType in $four {
  @include colorCombine("sc_color_", $linkType) {
    color: map.get($four-colors, #{$linkType}, "base");
  }
}

// 为了实现card组件中字体颜色和外框颜色一致  实现数字type匹配字体颜色 (和字符串颜色保持一致)
@each $linkType in $four {
  $i: index($four, $linkType);
  @include colorCombine("sc_color_", $i) {
    color: map.get($four-colors, #{$linkType}, "base");
  }
}

// 尺寸
@mixin sizeCombine($prefix, $type) {
  $fourName: $prefix + $type;
  .#{$fourName} {
    @content;
  }
}
@each $linkType in $size {
  @include colorCombine("sc-text--", $linkType) {
    font-size: map.get($sc_size, #{$linkType}, "size");
  }
}

//var.scss

$four: danger, warning, info, primary, purple, green, cyan, blue, normal, white; /*四色图( 重大危险 较大危险 一般分险 低分险) 后面颜色可扩展*/
$four-colors: (
  "danger": (
    "base": #ff3400,
    "type": 1,
  ),
  "warning": (
    "base": #ffab3f,
    "type": 2,
  ),
  "info": (
    "base": #f3ee55,
    "type": 3,
  ),
  "primary": (
    "base": #2ffff3,
    "type": 4,
  ),
  "purple": (
    "base": #9097ff,
    "type": 5,
  ),
  "green": (
    "base": #19ff70,
    "type": 6,
  ),
  "cyan": (
    "base": #00fcf7,
    "type": 7,
  ),
  "blue":
    (
      "base": #539cff,
      "type": 8,
    ),
  "normal": (
    "base": #0ceda8,
    "type": 9,
  ),
  "white": (
    "base": #fff,
    "type": 10,
  )
);

$size: large medium base small;
$sc_size: (
  "large": (
    "size": var(--sc-font-size-large),
  ),
  "medium": (
    "size": var(--sc-font-size-medium),
  ),
  "base": (
    "size": var(--sc-font-size-base),
  ),
  "small": (
    "size": var(--sc-font-size-small),
  ),
);

这里只是整体思路,可通过这种循环的方式生成一套类似与elementPlus的样式。写组件的时候只要使用这些类名即可。当然你也可以手动将elementPlus全局的变量值修改

  --el-text-color-primary: #00fcf7;
  --el-bg-color: #fff;

扩展:通过循环生成常用的css

// mt100,mr24,pl10,w100,h323
@for $i from 0 through 200 {
  .mt#{$i} {
    margin-top: 1px * $i;
  }
  .mb#{$i} {
    margin-bottom: 1px * $i;
  }
  .ml#{$i} {
    margin-left: 1px * $i;
  }
  .mr#{$i} {
    margin-right: 1px * $i;
  }
}
@for $i from 0 through 200 {
  .pt#{$i} {
    padding-top: 1px * $i;
  }
  .pb#{$i} {
    padding-bottom: 1px * $i;
  }
  .pl#{$i} {
    padding-left: 1px * $i;
  }
  .pr#{$i} {
    padding-right: 1px * $i;
  }
}
@for $i from 0 through 3000 {
  .w#{$i} {
    width: 1px * $i;
  }
  .h#{$i} {
    height: 1px * $i;
  }
}

你可能感兴趣的:(elementPlus,vue3)