sphere-hashes
A sphere for every name.
One function. A string goes in, an SVG comes out: a glass ball on a coloured ground, drawn from a hash of the string. The same seed gives the same sphere on every machine, with no network and no dependencies, in about 6 KB of SVG.
Built for placeholder avatars, but it works for anything that needs a stable picture for an id: people, workspaces, API keys, documents. Try the full tool, with the glass, at studiosphere.co/avatar.
Getting started
Import the function and give it a string. The result is the SVG as text.
import { sphereHash } from 'sphere-hashes'
const svg = sphereHash('finn@studiosphere.co')
// '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" ...'For an <img> or a CSS background there is a data URL version. One call, no file.
import { sphereHashUrl } from 'sphere-hashes'
const src = sphereHashUrl('finn@studiosphere.co', { size: 64 })
// 'data:image/svg+xml;charset=utf-8,%3Csvg...'That is the whole API for most uses.
In a component
React, with the data URL on an image.
import { sphereHashUrl } from 'sphere-hashes'
function Avatar({ id, size = 40 }) {
return <img src={sphereHashUrl(id, { size })} width={size} height={size} alt="" />
}Plain HTML, inline, which stays crisp at any size.
const el = document.querySelector('.avatar')
el.innerHTML = sphereHash('jesse', { shape: 'rounded' })Vue, Svelte and the rest work the same way: the function returns a string, put it where a string goes.
Seeds
Any string is a seed. A name, an email, a user id, a URL. The string is hashed, so nothing about it is in the picture, and two strings that differ by one letter give two unrelated spheres.
Whitespace at the ends is trimmed. An empty string still draws something.
Palettes
The palette sets the range the hues are drawn from. studio takes the whole wheel at a quiet saturation, warm and cool stay on their side of it, mono is greys with a hint of blue.
Shapes
The clip around the picture. The ground and the glow fill it, the ball sits in the middle.
Sizes
The viewBox is always 0 0 100 100, so an SVG scales to any size without a new render. size only sets the width and height attributes, for the places that read them, like an image tag or a favicon.
sphereHash('finn', { size: 256 })
// the same drawing, with width="256" height="256"Colours
sphereHashColors gives the four swatches behind a sphere, the ground, the cap, the band and the glow, as hex strings. Useful for a border, a text colour or a background that matches.
import { sphereHashColors, hash } from 'sphere-hashes'
sphereHashColors('finn') // ['#554ad7', '#1f2e34', '#2e4dd5', '#cca83c']
hash('finn') // 2323125802, the 32 bit hash everything is drawn fromOptions
The second argument. Every key is optional, an unknown value falls back to the default.
palettestudio, warm, cool, monostudioshapecircle, rounded, squarecirclesizethe width and height attributes, any number100Also exported: sphereHashUrl, sphereHashColors, hash, and the lists PALETTES and SHAPES. Types ship with the package.
How it works
The string is hashed with two rounds of integer mixing, and the hash seeds a small random generator. The generator picks a hue in the palette’s range, then the ground, the cap, the bands and the glow as offsets from it, so the colours of one sphere belong together. The band colours are interpolated in OKLab and sampled forty times, which is why the gradient on the ball melts rather than steps.
The glow under the ball is three blurred ellipses. The ball itself is the sphere mark from the Studio Sphere logo. The glass refraction in the tool is a WebGL pass on top of this SVG and stays in the tool: the SVG is the part that has to be the same everywhere, and it is.
Nothing is random at run time and nothing is fetched. Call it on the server, in a worker, in the browser, at build time. Same seed, same sphere.
Links
Code and issues on GitHub, the package on npm, the tool at studiosphere.co/avatar. MIT, Studio Sphere BV.