跳到主要内容

AvatarPro

长念
长念阅读约 6 分钟3 年前发布2 年前编辑
危险

✂️ 当前组件已停止更新维护,该文档已归档并停止更新。

基于 Avatar 组件封装的头像组件。

基本用法

特性说明

  • 支持文字多彩模式
  • 修复默认的 Avatar 组件缩放比例导致的文字倒置问题
  • 支持 AvatarProps 所有属性

何时使用

  • 如果遇到了文字头像倒置的问题 (已知在弹窗中使用 List 组件会出现此问题)
  • 如果需要用到多色文字头像

其他只是 Avatar 的简单应用并能实现效果时,不建议使用该组件

基本用法

import { AvatarPro } from 'hscs-common/components';

export default () => {
return (
<>
<AvatarPro colorful shape="square" size={48}>
你好
</AvatarPro>
<AvatarPro size={48}>你好</AvatarPro>
<AvatarPro colorful size={48}>
你好
</AvatarPro>
<AvatarPro colorful size={48}>
Hello
</AvatarPro>
<AvatarPro colorful size={48}>
안녕
</AvatarPro>
<AvatarPro colorful size={48}>
こんにちは
</AvatarPro>
<AvatarPro colorful size={48}>
<span role="img" aria-label="smile">
😄
</span>
</AvatarPro>
<AvatarPro colorful size={48}>
<span role="img" aria-label="imac">
🖥️
</span>
</AvatarPro>
</>
);
};

头像组

由于 Group 内部头像计数用到的组件是原始的 Avatar,所以也存在倒置问题,建议自定义实现 Group 功能。

import { Avatar } from 'choerodon-ui';
import { AvatarPro } from '@/components';

export default () => {
return (
<Avatar.Group maxCount={2} size={28} maxStyle={{ fontSize: 16 }}>
<AvatarPro colorful size={28} style={{ fontSize: 16 }}>
长念
</AvatarPro>
<AvatarPro colorful size={28} style={{ fontSize: 16 }}>
长念的小站
</AvatarPro>
<AvatarPro colorful size={28} style={{ fontSize: 16 }}>
ChangNian
</AvatarPro>
</Avatar.Group>
);
};

API

除此以下附加属性外,支持 Avatar 默认所有属性 AvatarProps

参数类型说明默认值
children
string | React.ReactElement
可选 子节点,递归查找 string 类型的子节点并显示 (Emoji 字符规范)-
colorfulboolean可选 是否启用多彩显示,仅 childrenstring 类型时有效false
modeAvatarMode可选 文本截取模式,枚举full_char

AvatarMode

export enum AvatarMode {
FirstChar = 'first_char',
First2Char = 'first_2char',
LastChar = 'last_char',
Last2Char = 'last_2char',
FullChar = 'full_char',
}

源代码

import type { AvatarProps } from 'choerodon-ui/lib/avatar';
import cls from 'classnames';
import * as React from 'react';
import AvatarP from './AvatarP';
import styles from './index.module.less';

// 预置头像色盘
const colorPalette = [
{ color: '#0840F8', backgroundColor: '#D6E4FF' },
{ color: '#722ED1', backgroundColor: '#EFDBFF' },
{ color: '#1890FF', backgroundColor: '#BAE7FF' },
{ color: '#13C2C2', backgroundColor: '#B5F5EC' },
{ color: '#52C41A', backgroundColor: '#D9F7BE' },
{ color: '#FA8C16', backgroundColor: '#FFE7BA' },
{ color: '#F5222D', backgroundColor: '#FFCCC7' },
{ color: '#FA541C', backgroundColor: '#FFD8BF' },
{ color: '#EB2F96', backgroundColor: '#FFD6E7' },
{ color: '#FAAD14', backgroundColor: '#FFF1B8' },
];

/**
* @description 获取头像配色
* @param text 展示字段值
*/
const getAvatarColor = (text = '-') => {
const charCode = text?.codePointAt(0) ?? 0;
const index = charCode % colorPalette.length;
return colorPalette[index];
};

// FIXED: 修复超出 UTF16 码元乱码问题
const getSliceString = (text = '-', length) => {
let sliceLength = Math.abs(length);
if (length === 1) {
sliceLength += text?.codePointAt(0) ?? 0 > 0xffff ? 1 : 0;
} else if (length === 2) {
if (text?.codePointAt(0) ?? 0 > 0xffff) {
sliceLength += 1;
if (text?.codePointAt(2) ?? 0 > 0xffff) {
sliceLength += 1;
}
}
} else if (length === -1) {
sliceLength += text?.codePointAt(text.length - 1) ?? 0 > 0xffff ? 1 : 0;
} else if (length === -2) {
if (text?.codePointAt(text.length - 1) ?? 0 > 0xffff) {
sliceLength += 1;
if (text?.codePointAt(text.length - 3) ?? 0 > 0xffff) {
sliceLength += 1;
}
}
}
return length > 0 ? text.slice(0, sliceLength) : text.slice(sliceLength * -1);
};

const getAvatarText = (children, mode = AvatarMode.FullChar) => {
if (typeof children !== 'string') {
if (children?.props?.children) {
return getAvatarText(children?.props?.children, mode);
}
// eslint-disable-next-line no-console
console.warn(`Warning: AvatarPro's children should be a string type.`);
return '-';
}

switch (mode) {
case AvatarMode.FirstChar:
return getSliceString(children, 1);
case AvatarMode.First2Char:
return getSliceString(children, 2);
case AvatarMode.LastChar:
return getSliceString(children, -1);
case AvatarMode.Last2Char:
return getSliceString(children, -2);
default:
return children;
}
};

export enum AvatarMode {
FirstChar = 'first_char',
First2Char = 'first_2char',
LastChar = 'last_char',
Last2Char = 'last_2char',
FullChar = 'full_char',
}

export type AvatarProProps = AvatarProps & {
/**
* @description 子节点
* @default '-'
*/
children?: string | React.ReactElement;

/**
* @description 文本截取模式
* @default 'full_char'
*/
mode?: AvatarMode;

/**
* @description 是否启用多彩模式
* @default false
*/
colorful?: boolean;
};

/**
* @see https://changnian.netlify.app/docs/c7n/custom-components/avatar-pro
*/
const AvatarPro: React.FC<AvatarProProps> = ({
children = '-',
colorful = false,
mode = AvatarMode.FullChar,
style,
className,
src,
...avatarProps
}) => {
const avatarText = !src ? getAvatarText(children, mode) : '';
const avatarColorStyle = !src && colorful ? getAvatarColor(avatarText) : {};

return (
<AvatarP
style={{ ...avatarColorStyle, ...style }}
className={cls(styles.avatar, className)}
shape="circle"
size={28}
src={src}
{...avatarProps}
>
{avatarText}
</AvatarP>
);
};

export default AvatarPro;

文字倒置修复

继承 Avatar 组件,覆盖 setScale 方法修复文字缩放倒置问题。

说明

AvatarP 组件是为了修复文字缩放倒置问题,也可以导入使用,AvatarPro 中就是以修复过后的 AvatarP 作为基础组件的。

此问题 (#1530) 已得到回复,预计将在后续版本 (>=1.6.3-alpha.3) 已修复。

AvatarP.tsx
import { Avatar } from 'choerodon-ui';
import { findDOMNode } from 'react-dom';
import { AvatarProps } from 'choerodon-ui/lib/avatar';
import { AvatarContextValue } from 'choerodon-ui/lib/avatar/AvatarContext';

export default class AvatarP extends Avatar {
constructor(props: AvatarProps, context: AvatarContextValue) {
super(props, context);
this.state = {
scale: 0.99999, // 避免等于1
isImgExist: true,
};
}

// 覆盖原方法:修复图像缩放问题
setScale = () => {
// eslint-disable-next-line react/no-find-dom-node
const avatarNode = findDOMNode(this) as HTMLElement;
if (avatarNode) {
const childNode = avatarNode.firstChild as HTMLElement;
const [avatarWidth, childWidth] = [avatarNode?.offsetWidth, childNode?.offsetWidth];
if (avatarWidth > 8 && avatarWidth - 8 < childWidth) {
this.setState({
scale: (avatarWidth - 8) / childWidth,
});
}
} else {
this.setState({ scale: 0.99999 });
}
};
}

多彩文字取色逻辑

const getAvatarColor = (text = '-') => {
const charCode = text?.codePointAt(0) ?? 0;
const index = charCode % colorPalette.length;
return colorPalette[index];
};

更新日志

0.1.1

  • 🎉 hscs-front-common@0.1.1 起支持该组件

alpha

2023-05-21

  • 🌶️ 舍弃 pinyin 取词库,采用 String.prototype.codePointAt() 实现
  • 🎉 扩展 children 类型
  • 🍋 优化部分逻辑

2023-05-15

  • 🎉 新增 AvatarP 组件修复原组件缩放导致的倒置问题;
  • 🍋 children 类型校验输出由错误调整为警告;