Icon组件
Icon组件,比较常用的做法就是通过一个create icon的方法,把svg转换成react组件,让svg的内容直接贴在html中。然后我们还希望能够控制svg的大小、颜色、是否旋转。
-
Color: 颜色的控制比较简单,就是通过fill="currentColor",然后外部的父元素的字体颜色,就会直接继承给svg。
-
Size: 大小就要通过传size属性值去控制,注意size可以传字符串(字体大小)也可以传字符串数组(宽高)。
-
Sprin: 这个通过写一个公共的旋转样式,当为true的时候就用上这个样式就好了。
icon.tsx
import { forwardRef, PropsWithChildren } from "react";
import cs from 'classnames';
import './index.scss';
type BaseIconProps = {
className?: string;
style?: React.CSSProperties;
size?: string | string[];
spin?: boolean;
}
export type IconProps = PropsWithChildren<BaseIconProps & Omit<React.SVGAttributes<SVGElement>, keyof BaseIconProps>>;
// ['10px', '20px'] or '10px'
// 如果传了['10px'] 则等宽高10px
export const getSize = (size: IconProps['size']) => {
if (Array.isArray(size) && size.length === 2) {
return size;
}
const width = (size as string) || '1em';
const height = (size as string) || '1em';
return [width, height];
}
export const Icon = forwardRef<SVGSVGElement, IconProps>(
(props, ref) => {
const {
style,
className,
children,
size,
spin,
...restProps
} = props;
const [width, height] = getSize(size);
const cn = cs('icon', { 'icon-spin': spin }, className);
return (
<svg ref={ref} className={cn} style={style} width={width} height={height} fill="currentColor" {...restProps}>
{children}
</svg>
)
}
)
icon.scss
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.icon {
display: inline-block;
}
.icon-spin {
animation: spin 1s linear infinite;
}
为了方便使用,再写一个创建icon的工厂函数, 这里在参数上的设计,有一点想法。
createIcon:定义svg元素的固有属性,所以把viewBox放在这一层。
icon:定义svg元素的个性化属性
import React, { forwardRef } from "react";
import { IconProps, Icon } from "./Icon";
export interface CreateIconOptions {
content: React.ReactNode;
iconProps?: IconProps;
viewBox?: string;
}
export const createIcon = (options: CreateIconOptions) => {
const { content, iconProps = {}, viewBox='0, 0, 1024, 1024' } = options;
return forwardRef<SVGSVGElement, IconProps>((props, ref) => {
return <Icon ref={ref} viewBox={viewBox} {...iconProps} {...props} >
{content}
</Icon>;
})
}
然后就可以去创建我们的icon组件了。
import { createIcon } from '../createIcon';
export const IconAdd = createIcon({
content: (
<>
<path d="M853.333333 480H544V170.666667c0-17.066667-14.933333-32-32-32s-32 14.933333-32 32v309.333333H170.666667c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h309.333333V853.333333c0 17.066667 14.933333 32 32 32s32-14.933333 32-32V544H853.333333c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32z"></path>
</>
),
});

浙公网安备 33010602011771号