Задача: если не задано изображение, выводить первую букву имени и цвет для аватара. Примерно как
в telegram или google. Палитра цветов задана. Чем меньше в ней цветов, тем больше их совпадений.
Как вариант, можно генерировать цвета в hsl, управляя насыщенностью - то же самое, только тонко
палитрой управлять не получится, зато и коллизий меньше.
Цвет не должен меняться рандомно, поэтому потребуется механизм «запоминания». Для этого будем получать простенький хэш из имени пользователя. А уже из него добывать цвет.
// Получаем значение из имени пользователяconst getHashOfString =(str:string):number=>{let hash =0;for(let i =0; i < str.length; i +=1){
hash = str.charCodeAt(i)+((hash <<5)- hash);}
hash = Math.abs(hash);return hash;};// Приводим его к нужному диапазонуconst normalizeHash =(hash:number, min:number, max:number):number=>
Math.floor((hash %(max - min))+ min);// Вынимаем из палитры один из цветовexportconstgetColorFromPalette=(name:string, palette:string[])=>
palette[normalizeHash(getHashOfString(name),0, palette.length -1)];
import React,{ memo }from'react';import{ Image, Text, View, StyleSheet }from'react-native';import{ getColorFromPalette }from'./getColorFromPalette';import{ palette }from'./palette';interfaceIAvatar{
name:string;
sizes?:{
width:number;
height:number;};
radius?:number;
source?:string;
extraStyles?: object;}const styles = StyleSheet.create({
image:{
resizeMode:'cover',},
avatar:{
backgroundColor:'#FD6B6F',
alignItems:'center',
justifyContent:'center',},
text:{
color:'white',
fontWeight:'bold',},});/* Принимает в качестве аргументов:
source - адрес изображения
sizes - размеры аватара
radius - радиус углов
name - имя пользователя
extraStyles - возможность внешней стилизации
*/const Avatar: React.FC<IAvatar>=({
source ='',
sizes ={ width:scale(30), height:scale(30)},
radius =100,
name ='',
extraStyles ={},})=>{const userName = name ? name[0]?.toUpperCase():'A';// размер шрифта зависит от размера аватараconst textSize = sizes && sizes.height ? sizes.height /1.5:18;return source ?(<Imagesource={{uri: source }}style={[styles.image, sizes,{borderRadius: radius }, extraStyles]}/>):(<Viewstyle={[
styles.avatar,
sizes,{borderRadius: radius,backgroundColor:getColorFromPalette(name, palette)||'#FD6B6F',},
extraStyles,]}><Textstyle={[styles.text,{fontSize: textSize }]}>{userName}</Text></View>);};
Avatar.displayName ='Avatar';exportdefaultmemo(Avatar);
Код компонента написан для React Native, но изменить его несложно.