前言:
部分UI库组件的Button组件无法自定义颜色,定制颜色变量又无法很好的适配点击效果和hover效果
这里以semi UI库进行举例,过程略微麻烦,看懂直接粘贴
原文地址:https://www.yuque.com/suancairiji/sqowo1/mcxec1tcdghqi30r?singleDoc# 《react – 封装UI库按钮颜色自定义算法》
核心:十六进制颜色转十进制颜色切加深颜色算法
因为我们平时使用十六进制的多一些,但是加深颜色又需要转换为十进制进行计算
/**
* 颜色加深算法
* @params hexColor 十六进制颜色 #fffff
* @params percentage 加深值 默认0.1
*/
export function darkenColor(hexColor: string, percentage = 0.1): string {
hexColor = hexColor.replace("#", "");
// 拆分颜色值
const r = parseInt(hexColor.substr(0, 2), 16);
const g = parseInt(hexColor.substr(2, 2), 16);
const b = parseInt(hexColor.substr(4, 2), 16);
// 计算加深后的颜色值
const darkenR = Math.round(r * (1 - percentage));
const darkenG = Math.round(g * (1 - percentage));
const darkenB = Math.round(b * (1 - percentage));
// 返回加深后的十进制颜色代码
return `${darkenR}, ${darkenG}, ${darkenB}`;
}
经过darkenColor方法转换处理为加深后可用的十进制rgb颜色
封装:按钮组件
有几点需要注意的bug:
1、为何要使用onMouseLeave 再次执行
答:多数UI库的Popover组件 是绑定依赖组件的真实dom后进行赋值onMouseLeave方法,会给我们的onMouseLeave方法相互抵消,所以这里判断一下是否存在onMouseLeave传入并执行
2、为何要使用forwardRef包裹
答:多数UI库的Popover组件 是依赖绑定组件的真实dom进行定位的,需要给到父组件ref才不会出现定位异常的bug
import { Button } from "@douyinfe/semi-ui";
import { ButtonProps } from "@douyinfe/semi-ui/lib/es/button";
import React, {
useEffect,
forwardRef,
useState,
} from "react";
import { darkenColor } from "@/utils/useHook.ts";
type ButtonsProps = {
background?: string;
color?: string;
};
/**
* 按钮组件-- 可修改颜色
*/
function Buttons(props: ButtonsProps & ButtonProps, ref: any) {
const { background = "#fff", color = "#fff" } = props;
const [isHover, setIsHover] = useState(false);
const [isClick, setIsClick] = useState(false);
const [hoverColor, setHoverColor] = useState("");
const [clickColor, setClickColor] = useState("");
useEffect(() => {
initColor();
console.log(background);
}, []);
//初始化按钮颜色
const initColor = () => {
const HoverColor = darkenColor(background, 0.05);
const ClickColor = darkenColor(background, 0.1);
setHoverColor(`rgb(${HoverColor})`);
setClickColor(`rgb(${ClickColor})`);
};
const onMouseLeave = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
const { onMouseLeave } = props;
setIsHover(false);
onMouseLeave && onMouseLeave(event);
};
const onMouseEnter = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
const { onMouseEnter } = props;
setIsHover(true);
onMouseEnter && onMouseEnter(event);
};
const onMouseDown = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
const { onMouseDown } = props;
setIsClick(true);
onMouseDown && onMouseDown(event);
};
const onMouseUp = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
const { onMouseUp } = props;
setIsClick(false);
onMouseUp && onMouseUp(event);
};
return (
<Button
ref={ref}
{...props}
style={{
color,
backgroundColor: isHover ? (isClick ? clickColor : hoverColor) : background,
}}
onMouseLeave={onMouseLeave}
onMouseEnter={onMouseEnter}
onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
>
{props.children}
</Button>
);
}
export default forwardRef(Buttons);
调用组件
封装后不仅继承了原按钮组件所有的props,并且可以开心的随意修改颜色,不用一个一个单独去修改css了
<Buttons
background="#ee5959"
theme="solid"
type="primary"
>
登 录
</Buttons>