近日,保利威前端开发者在技术平台发布了实践分享,提供其B端直播平台品牌色功能的迭代方案。针对企业用户对直播系统“品牌视觉适配”的需求,保利威团队从技术层面拆解了品牌色功能的实现逻辑,解决了B端场景下品牌色个性化配置的技术痛点,为企业直播平台的视觉定制化提供了可复用的落地路径。

-以下为Blog文稿搬运-

最近产品经理希望在 B 端后台系统中增加品牌色功能,突显客户的企业特色。从技术上说,整个流程是非常简单的:

  1. 在配置中心为某个客户配置品牌色(十六进制颜色值)。
  2. 后台系统初始化时,通过后端接口读取配置的品牌色。
  3. 把品牌色写入为根元素的 CSS 变量

核心流程代码如下:

const response = await fetch('/api/get-brand-info'); 
const data = await response.json(); 
document.documentElement.style.setProperty(
 '--brand-primary-color', 
data.primaryColor
 ); 

颜色替换

接下来要把项目中样式代码的颜色值改为 CSS 变量。颜色值的使用,一般有两种情况:

  • 使用了 SCSS 等 CSS 扩展语言中的变量,所有颜色值都从变量取值;
  • 直接用颜色值。

实际情况更有可能是这两种的混合——虽然使用了 SCSS 变量,但由于部分开发人员没有完全遵循规范,所以项目中既有颜色变量,也有颜色值

$primary-color: #3F76FC; 
.logo { 
background: #3F76FC;
 }
 .selected { 
color: $primary-color; 
border: 1px solid $primary-color;
 background: rgba($primary-color, 0.1);
 }

不过,不管是哪种情况,似乎都是把颜色值替换成 CSS 变量就可以了。以上述代码为例,即把「#3F76FC」替换为「var(–brand-primary-color, #3F76FC)」:

$primary-color: var(--brand-primary-color, #3F76FC); 
.logo { 
background: var(--brand-primary-color, #3F76FC);
 }
 .selected { 
color: $primary-color;
 border: 1px solid $primary-color;
 background: rgba($primary-color, 0.1);
 }

替换后,马上发现问题——.selected 元素的背景色没了。通过浏览器开发工具可以发现,背景属性的值变成了:

background: rgba(var(--brand-primary-color, #3F76FC), 0.1);

属于无效写法。造成这种情况,是因为「background: rgba($primary-color, 0.1)」中的「$primary-color」被编译成该变量的值了。

在 SCSS 中,可以用「rgba(#3F76FC, 0.1)」这种写法。编译过程中,编译器会把十六进制颜色值转成 RGB 颜色值,也就是编译成「rgba(63, 118, 252, 0.1)」。然而,把颜色值替换成 CSS 变量后,由于编译器也不知道颜色值是什么,所以无法进行转换。因此,这里必须用 RGB 颜色值

对核心流程代码稍作修改,设置两个 CSS 变量,分别是 RGB 颜色值和十六进制颜色值:

import { hexToRGB } from '@polyv/utils/es/color'; 
const response = await fetch('/api/get-theme'); 
const data = await response.json();
 document.documentElement.style.setProperty( 
'--brand-primary-color-hex',
 data.primaryColor
 );
 document.documentElement.style.setProperty( 
'--brand-primary-color-rgb',
 hexToRGB(data.primaryColor).join(',') 
); 

接下来设置两个 SCSS 变量,分别是品牌色的十六进制表示和 RGB 表示:

$--primary-color-hex: var(--brand-primary-color-hex, #3F76FC);
 $--primary-color-rgb: var(--brand-primary-color-rgb, 63, 118, 252);

做两次替换操作:

  1. 把「rgba($–primary-color」以及「rgba(#3F76FC」替换为「rgba($–primary-color-rgb」。
  2. 把剩余的「$–primary-color」以及「#3F76FC」替换为「$–primary-color-hex」。

最终能正常运行的代码为:

$--primary-color-hex: var(--brand-primary-color-hex, #3F76FC);
 $--primary-color-rgb: var(--brand-primary-color-rgb, 63, 118, 252);
 .logo { 
background: $--primary-color-hex;
 } 
.selected {
 color: $--primary-color-hex;
 border: 1px solid $--primary-color-hex;
 background: rgba($--primary-color-rgb, 0.1);
 }

颜色计算

设计师希望后台系统左侧导航栏的底色是通过 25% 不透明度的品牌色叠加黑色得出。

 

虽说通过两个 HTML 元素叠加,就能做到这个效果,但是 HTML 结构和样式代码都会稍显复杂。通过 JavaScript 去计算出这个颜色值就方便多了:

export function mixWithBlack(color, opacity) { 
const r = parseInt(hex.slice(0, 2), 16) * opacity; 
const g = parseInt(hex.slice(2, 4), 16) * opacity; 
const b = parseInt(hex.slice(4, 6), 16) * opacity;
 const toHex = (c) => c.toString(16).padStart(2, '0');
 return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
 } 
 
document.documentElement.style.setProperty( 
'--brand-nav-bg-color', 
mixWithBlack(data.primaryColor, 0.25) 
); 

如果还有更复杂的颜色计算,也可以使用专业的第三方库,如 tinycolor

最终效果