🎨
頭文字ランダムカラーアバターを生成する mui + TypeScript
概要
よくあるこうゆうやつを作る方法です。
現在開発中のアプリで各地方自治体のアバターとして表示する要件があり作成しました。
できるだけカラーをばらつかせたかったので、色は地方公共団体コードから算出することを前提に作りっています。
またアプリのUI的に余り明度が高すぎる色は出したくなかったので、明度が80%まででカラーピックされるようにしています。
参考
Auto generate unique Avatar colors randomly - DEV Community 👩💻👨💻
実装
アバターを表示する GovtAvatar
コンポーネントとアバター用の頭文字と色を返してくれる createAvatar
関数で構成しています。
GovtAvatar
GovtAvatar.tsx
import createAvatar from '../../utils/createAvatar';
import { Avatar } from '..';
// ----------------------------------------------------------------------
type Props = {
name: string;
gcode: string;
url?: string;
};
export default function GovtAvatar({ name, gcode, url }: Props) {
const avatar = createAvatar(name, gcode);
return (
<Avatar src={url} alt={name} color={avatar.color} sx={{ color: avatar.contrast }}>
{avatar.name}
</Avatar>
);
}
mui
の Avatar
コンポーネントを使用して画像のurl指定がある場合はそれを、ない場合は頭文字とピックされたカラーで表示されるようにしています。
createAvatar
createAvatar
は第1引数 name
を渡すだけならカラーピックにその文字列も利用しますが、第2引数 forColor
を渡すとカラーピック用にはそちらの文字列を利用します。
getAvatarColor
は渡された文字列をもとにランダムなカラーのHSLを color
プロパティで返します。
また、選ばれたカラーの明るさに応じて、アバターの文字用のカラーを contrast
プロパティで返します。
createAvatar.ts
const normalizeHash = (hash: number, min: number, max: number) =>
Math.floor((hash % (max - min)) + min);
const generateHSL = (name: string) => {
const hRange = [0, 360];
const sRange = [0, 100];
const lRange = [0, 80];
const hash = isNaN(Number(name)) ? name.length : Number(name);
const h = normalizeHash(hash, hRange[0], hRange[1]);
const s = normalizeHash(hash, sRange[0], sRange[1]);
const l = normalizeHash(hash, lRange[0], lRange[1]);
return [h, s, l];
};
const getFirstChar = (name: string) => name && name.charAt(0).toUpperCase();
const getAvatarColor = (name: string) => {
const hsl = generateHSL(name);
return {
color: `hsl(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%)`,
contrast: hsl[2] >= 50 ? '#555555' : '#ffffff',
};
};
export default function createAvatar(name: string, forColor?: string) {
const forGenColor = forColor ? forColor : name;
const { color, contrast } = getAvatarColor(forGenColor);
return {
name: getFirstChar(name),
color,
contrast,
} as const;
}
Discussion