Update gradient algorithm to use a seed value for predictable gradients and use app names for seeds

This commit is contained in:
Andrew Kingston 2021-05-10 15:28:52 +01:00
parent 99ff417aa8
commit 2421529ba8
3 changed files with 46 additions and 20 deletions

View File

@ -1,9 +1,10 @@
export const gradient = (node, config = {}) => { export const gradient = (node, config = {}) => {
const defaultConfig = { const defaultConfig = {
points: 10, points: 12,
saturation: 0.8, saturation: 0.85,
lightness: 0.7, lightness: 0.7,
softness: 0.9, softness: 0.9,
seed: null,
} }
// Applies a gradient background // Applies a gradient background
@ -13,42 +14,67 @@ export const gradient = (node, config = {}) => {
...config, ...config,
} }
const { saturation, lightness, softness, points } = config const { saturation, lightness, softness, points } = config
const seed = config.seed || Math.random().toString(32).substring(2)
// Generates a random number between min and max // Hash function which returns a fixed hash between specified limits
const rand = (min, max) => { // for a given seed and a given version
return Math.round(min + Math.random() * (max - min)) const rangeHash = (seed, min = 0, max = 100, version = 0) => {
const range = max - min
let hash = range + version
for (let i = 0; i < seed.length * 2 + version; i++) {
hash = (hash << 5) - hash + seed.charCodeAt(i % seed.length)
hash = ((hash & hash) % range) + version
}
return min + (hash % range)
} }
// Generates a random HSL colour using the options specified // Generates a random HSL colour using the options specified
const randomHSL = () => { const randomHSL = (seed, version, alpha = 1) => {
const lowerSaturation = Math.min(100, saturation * 100) const lowerSaturation = Math.min(100, saturation * 100)
const upperSaturation = Math.min(100, (saturation + 0.2) * 100) const upperSaturation = Math.min(100, (saturation + 0.2) * 100)
const lowerLightness = Math.min(100, lightness * 100) const lowerLightness = Math.min(100, lightness * 100)
const upperLightness = Math.min(100, (lightness + 0.2) * 100) const upperLightness = Math.min(100, (lightness + 0.2) * 100)
const hue = rand(0, 360) const hue = rangeHash(seed, 0, 360, version)
const sat = `${rand(lowerSaturation, upperSaturation)}%` const sat = `${rangeHash(
const light = `${rand(lowerLightness, upperLightness)}%` seed,
return `hsl(${hue},${sat},${light})` lowerSaturation,
upperSaturation,
version
)}%`
const light = `${rangeHash(
seed,
lowerLightness,
upperLightness,
version
)}%`
return `hsla(${hue},${sat},${light},${alpha})`
} }
// Generates a radial gradient stop point // Generates a radial gradient stop point
const randomGradientPoint = () => { const randomGradientPoint = (seed, version) => {
const lowerTransparency = Math.min(100, softness * 100) const lowerTransparency = Math.min(100, softness * 100)
const upperTransparency = Math.min(100, (softness + 0.2) * 100) const upperTransparency = Math.min(100, (softness + 0.2) * 100)
const transparency = rand(lowerTransparency, upperTransparency) const transparency = rangeHash(
seed,
lowerTransparency,
upperTransparency,
version
)
return ( return (
`radial-gradient(` + `radial-gradient(at ` +
`at ${rand(10, 90)}% ${rand(10, 90)}%,` + `${rangeHash(seed, 0, 100, version)}% ` +
`${randomHSL()} 0,` + `${rangeHash(seed, 0, 100, version + 1)}%,` +
`${randomHSL(seed, version, saturation)} 0,` +
`transparent ${transparency}%)` `transparent ${transparency}%)`
) )
} }
let css = `opacity:0.9;background-color:${randomHSL()};background-image:` let css = `opacity:0.9;background:${randomHSL(seed, 0, 0.7)};`
css += "background-image:"
for (let i = 0; i < points - 1; i++) { for (let i = 0; i < points - 1; i++) {
css += `${randomGradientPoint()},` css += `${randomGradientPoint(seed, i)},`
} }
css += `${randomGradientPoint()};` css += `${randomGradientPoint(seed, points)};`
node.style = css node.style = css
} }

View File

@ -18,7 +18,7 @@
<div class="wrapper"> <div class="wrapper">
<Layout noPadding gap="XS" alignContent="start"> <Layout noPadding gap="XS" alignContent="start">
<div class="preview" use:gradient /> <div class="preview" use:gradient={{ seed: app.name }} />
<div class="title"> <div class="title">
<Link href={$url(`../../app/${app._id}`)}> <Link href={$url(`../../app/${app._id}`)}>
<Heading size="XS"> <Heading size="XS">

View File

@ -18,7 +18,7 @@
</script> </script>
<div class="title" class:last> <div class="title" class:last>
<div class="preview" use:gradient /> <div class="preview" use:gradient={{ seed: app.name }} />
<Link href={$url(`../../app/${app._id}`)}> <Link href={$url(`../../app/${app._id}`)}>
<Heading size="XS"> <Heading size="XS">
{app.name} {app.name}