Switch to HSL for avatar generation

This commit is contained in:
Jonathan Staab 2023-03-13 14:54:59 -05:00
parent 5e19ceb99a
commit c1f7a30a85
7 changed files with 36 additions and 105 deletions

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg fill="#eb5e28" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="800px" height="800px" viewBox="0 -10 409.165 409.164"
xml:space="preserve">
<g>
<g>
<path d="M204.583,216.671c50.664,0,91.74-48.075,91.74-107.378c0-82.237-41.074-107.377-91.74-107.377
c-50.668,0-91.74,25.14-91.74,107.377C112.844,168.596,153.916,216.671,204.583,216.671z"/>
<path d="M407.164,374.717L360.88,270.454c-2.117-4.771-5.836-8.728-10.465-11.138l-71.83-37.392
c-1.584-0.823-3.502-0.663-4.926,0.415c-20.316,15.366-44.203,23.488-69.076,23.488c-24.877,0-48.762-8.122-69.078-23.488
c-1.428-1.078-3.346-1.238-4.93-0.415L58.75,259.316c-4.631,2.41-8.346,6.365-10.465,11.138L2.001,374.717
c-3.191,7.188-2.537,15.412,1.75,22.005c4.285,6.592,11.537,10.526,19.4,10.526h362.861c7.863,0,15.117-3.936,19.402-10.527
C409.699,390.129,410.355,381.902,407.164,374.717z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,28 +1,23 @@
<svg
class={$$props.class}
{...$$props}
width="189"
height="189"
viewBox="0 0 189 189"
fill="none"
xmlns="http://www.w3.org/2000/svg"
style={$$props.style}
>
xmlns="http://www.w3.org/2000/svg">
<g id="paths" clip-path="url(#clip0_753_289)" style="stroke: var(--logo-color, #EB5E28)">
<path
d="M43.7937 12.5298C0.57938 44.8609 0.342815 92.8076 16.3236 126.458C33.6361 162.913 75.9226 184.525 117.769 173.613C156.42 163.534 183.82 122.549 182.358 95.8221"
stroke-width="12"
stroke-linecap="round"
/>
stroke-linecap="round" />
<path
d="M78.6923 75.6945C50.8177 86.6612 44.0155 112.559 47.9751 133.172C52.2646 155.502 72.1284 173.572 96.2818 173.985C118.59 174.366 139.116 156.332 142.045 141.655"
stroke-width="12"
stroke-linecap="round"
/>
stroke-linecap="round" />
<path
d="M43.5856 12.4047C17.9702 31.569 17.83 59.9895 27.3026 79.936C37.5646 101.545 62.6301 114.355 87.4348 107.887C110.345 101.913 126.587 77.6188 125.72 61.7764"
stroke-width="12"
stroke-linecap="round"
/>
stroke-linecap="round" />
</g>
<defs>
<clipPath id="clip0_753_289">

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,27 +1,29 @@
<script lang="ts">
import { generateAvatarColors } from "src/util/misc";
import ImageCircle from "./ImageCircle.svelte";
import LogoSvg from "./LogoSvg.svelte";
import cx from "classnames";
import type { Person } from "src/util/types"
import {stringToHue, hsl} from "src/util/misc"
import ImageCircle from "src/partials/ImageCircle.svelte"
import LogoSvg from "src/partials/LogoSvg.svelte"
import cx from "classnames"
export let person : Person;
export let size = 4;
export let person
export let size = 4
$: avatarColor = person.kind0 && !person.kind0.picture
? generateAvatarColors(person.pubkey)
: { primary: '#EB5E28', bg: 'transparent' };
const hue = stringToHue(person.pubkey)
const primary = hsl(hue, {lightness: 80})
const secondary = hsl(hue, {saturation: 30, lightness: 30})
</script>
{#if person.kind0?.picture}
{#if false && person.kind0?.picture}
<ImageCircle {size} src={person.kind0.picture} class={$$props.class} />
{:else}
<ImageCircle
{size}
src={""}
class={cx($$props.class, "relative")}
style="--logo-color: {avatarColor.primary}; --logo-bg-color: {avatarColor.bg}; background-color: var(--logo-bg-color);"
>
<LogoSvg class="absolute left-2/4 top-2/4 -translate-x-1/2 -translate-y-1/2 logo" style="height: 85%; width: 85%;" />
</ImageCircle>
<div
class={cx(
$$props.class,
`relative overflow-hidden w-${size} h-${size} inline-block shrink-0 rounded-full border border-solid
border-white bg-cover bg-center`
)}
style="--logo-color: {primary}; --logo-bg-color: {secondary}; background-color: var(--logo-bg-color);">
<LogoSvg
class="logo absolute left-2/4 top-2/4 -translate-x-1/2 -translate-y-1/2"
style="height: 85%; width: 85%;" />
</div>
{/if}

View File

@ -2,7 +2,7 @@
import cx from "classnames"
import {last} from "ramda"
import {onMount} from "svelte"
import {poll, stringToColor} from "src/util/misc"
import {poll, stringToHue, hsl} from "src/util/misc"
import {between} from "hurdak/lib/hurdak"
import {fly} from "svelte/transition"
import Anchor from "src/partials/Anchor.svelte"
@ -36,7 +36,7 @@
`bg-${theme}`,
"flex flex-col justify-between gap-3 rounded border border-l-2 border-solid border-medium py-3 px-6 shadow"
)}
style={`border-left-color: ${stringToColor(relay.url)}`}
style={`border-left-color: ${hsl(stringToHue(relay.url))}`}
in:fly={{y: 20}}>
<div class="flex items-center justify-between gap-2">
<div class="flex items-center gap-2 text-xl">

View File

@ -1,7 +1,7 @@
<script lang="ts">
import {last} from "ramda"
import {fly} from "svelte/transition"
import {stringToColor} from "src/util/misc"
import {stringToHue, hsl} from "src/util/misc"
export let relay
</script>
@ -9,7 +9,7 @@
<div
class="flex flex-col justify-between gap-3 rounded border border-l-2 border-solid
border-medium py-3 px-6 shadow"
style={`border-left-color: ${stringToColor(relay.url)}`}
style={`border-left-color: ${hsl(stringToHue(relay.url))}`}
in:fly={{y: 20}}>
<div class="flex items-center justify-between gap-2">
<div class="flex items-center gap-2 text-xl">

View File

@ -1,7 +1,7 @@
<script lang="ts">
import {find, propEq} from "ramda"
import {onMount} from "svelte"
import {poll, stringToColor} from "src/util/misc"
import {poll, stringToHue, hsl} from "src/util/misc"
import {displayRelay} from "src/util/nostr"
import {between} from "hurdak/lib/hurdak"
import Content from "src/partials/Content.svelte"
@ -44,7 +44,7 @@
<div class="flex items-center justify-between gap-2">
<div class="flex items-center gap-2 text-xl">
<i class={relay.url.startsWith("wss") ? "fa fa-lock" : "fa fa-unlock"} />
<span class="border-b border-solid" style={`border-color: ${stringToColor(relay.url)}`}>
<span class="border-b border-solid" style={`border-color: ${hsl(stringToHue(relay.url))}`}>
{displayRelay(relay)}
</span>
<span

View File

@ -5,7 +5,6 @@ import Fuse from "fuse.js/dist/fuse.min.js"
import {writable} from 'svelte/store'
import {isObject, round} from 'hurdak/lib/hurdak'
import {warn} from 'src/util/logger'
import {memoizeWith} from 'ramda';
export const fuzzy = (data, opts = {}) => {
const fuse = new Fuse(data, opts)
@ -271,65 +270,18 @@ export const where = filters =>
)
// https://stackoverflow.com/a/21682946
//
export const stringToColor = (value, {saturation = 100, lightness = 50, opacity = 1} = {}) => {
export const stringToHue = value => {
let hash = 0;
for (let i = 0; i < value.length; i++) {
hash = value.charCodeAt(i) + ((hash << 5) - hash)
hash = hash & hash
}
return `hsl(${(hash % 360)}, ${saturation}%, ${lightness}%, ${opacity})`;
return hash % 360
}
// https://stackoverflow.com/a/75255491
const stringToHex = function(str: string) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
let colour = '#';
for (let i = 0; i < 3; i++) {
let value = (hash >> (i * 8)) & 0xFF;
colour += ('00' + value.toString(16)).substr(-2);
}
return colour;
}
function padZero(str: string, len?: number) {
len = len || 2;
let zeros = new Array(len).join('0');
return (zeros + str).slice(-len);
}
// https://stackoverflow.com/a/35970186
function invertColor(hex: string) {
if (hex.indexOf('#') === 0) {
hex = hex.slice(1);
}
// convert 3-digit hex to 6-digits.
if (hex.length === 3) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
if (hex.length !== 6) {
throw new Error('Invalid HEX color.');
}
// invert color components
let r = (255 - parseInt(hex.slice(0, 2), 16)).toString(16),
g = (255 - parseInt(hex.slice(2, 4), 16)).toString(16),
b = (255 - parseInt(hex.slice(4, 6), 16)).toString(16);
// pad each with zeros and return
return '#' + padZero(r) + padZero(g) + padZero(b);
}
export const generateAvatarColors = memoizeWith(identity, (pubkey: string) => {
const primary = stringToHex(pubkey);
return {
primary,
bg: invertColor(primary),
}
});
export const hsl = (hue, {saturation = 100, lightness = 50, opacity = 1} = {}) =>
`hsl(${hue}, ${saturation}%, ${lightness}%, ${opacity})`
export const tryFunc = (f, ignore = null) => {
try {