mirror of https://github.com/msgbyte/tailchat
parent
96ddcb312a
commit
944d7a7c72
@ -0,0 +1,42 @@
|
||||
import { fetchImagePrimaryColor } from '@/utils/image-helper';
|
||||
import React from 'react';
|
||||
import { AvatarWithPreview, getTextColorHex } from 'tailchat-design';
|
||||
import { useAsync, UserBaseInfo } from 'tailchat-shared';
|
||||
|
||||
/**
|
||||
* 用户信息容器
|
||||
*/
|
||||
export const UserProfileContainer: React.FC<{ userInfo: UserBaseInfo }> =
|
||||
React.memo((props) => {
|
||||
const { userInfo } = props;
|
||||
const { value: bannerColor } = useAsync(async () => {
|
||||
if (!userInfo.avatar) {
|
||||
return getTextColorHex(userInfo.nickname);
|
||||
}
|
||||
|
||||
const rgba = await fetchImagePrimaryColor(userInfo.avatar);
|
||||
return `rgba(${rgba.r}, ${rgba.g}, ${rgba.b}, ${rgba.a})`;
|
||||
}, [userInfo.avatar]);
|
||||
return (
|
||||
<div className="relative bg-inherit">
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
height: 60,
|
||||
backgroundColor: bannerColor,
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="absolute p-1 rounded-1/2 -mt-11 ml-3 bg-inherit">
|
||||
<AvatarWithPreview
|
||||
size={80}
|
||||
src={userInfo.avatar}
|
||||
name={userInfo.nickname}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="p-2 mt-10">{props.children}</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
UserProfileContainer.displayName = 'UserProfileContainer';
|
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 加载图片
|
||||
*/
|
||||
async function loadImage(url: string): Promise<HTMLImageElement> {
|
||||
const el = document.createElement('img');
|
||||
return new Promise((resolve, reject) => {
|
||||
el.onload = () => resolve(el);
|
||||
el.onerror = reject;
|
||||
el.src = url;
|
||||
el.crossOrigin = 'Anonymous';
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图片的主要颜色
|
||||
*/
|
||||
export async function fetchImagePrimaryColor(imageUrl: string) {
|
||||
const img = await loadImage(imageUrl);
|
||||
const canvas = document.createElement('canvas');
|
||||
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) {
|
||||
return { r: 0, g: 0, b: 0, a: 0 };
|
||||
}
|
||||
|
||||
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
|
||||
let r = 0;
|
||||
let g = 0;
|
||||
let b = 0;
|
||||
let a = 0;
|
||||
|
||||
for (let row = 0; row < imageData.height; row++) {
|
||||
for (let col = 0; col < imageData.width; col++) {
|
||||
r += imageData.data[(imageData.width * row + col) * 4];
|
||||
g += imageData.data[(imageData.width * row + col) * 4 + 1];
|
||||
b += imageData.data[(imageData.width * row + col) * 4 + 2];
|
||||
a += imageData.data[(imageData.width * row + col) * 4 + 3];
|
||||
}
|
||||
}
|
||||
|
||||
const sum = imageData.width * imageData.height;
|
||||
r = Math.round(r / sum);
|
||||
g = Math.round(g / sum);
|
||||
b = Math.round(b / sum);
|
||||
a = Math.round(a / sum);
|
||||
|
||||
return {
|
||||
r,
|
||||
g,
|
||||
b,
|
||||
a,
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue