import { routes } from '@redwoodjs/router' import { MetaTags } from '@redwoodjs/web' import { useEffect, useState } from 'react' import { Slider, SliderTrack, SliderFilledTrack, SliderThumb, SliderMark, Box, Center, Square, Flex, Text, Link, Button, Stack, HStack, VStack, Container, Image, Accordion, AccordionItem, AccordionButton, AccordionPanel, AccordionIcon, Heading } from '@chakra-ui/react' import Jimp from 'jimp' import fileDownload from 'js-file-download' import convert from 'color-convert' const HomePage = () => { const [h, setH] = useState(100.0) const [s, setS] = useState(0) const [iconB64, setIconB64] = useState("data:image/png;base64,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AAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAABhAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAABhAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAABhAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAMIAAABhAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAMIAAABhAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACABhAAAAMIAAABhAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACABhAAAAMIAAABhAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAMIASAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAAAGEAAAAwgAgAEEADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAAAGEAAAAwgAgAEEADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAAAGEAAAAwgAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAAAGEAAAAwgAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAAAGEADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAAAGEADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAAAGEADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAABhAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAABhAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAABhAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAMIAAABhAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAMIAAABhAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACABhAAAAMIAAABhAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACABhAAAAMIAAABhAAAAMIAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAMIASAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAAAGEAAAAwgAgAEEADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAAAGEAAAAwgAgAEEADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAAAGEAAAAwgAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAAAGEAAAAwgAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAAAGEADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAAAGEADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAAAGEADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAIABBADAAAIAYAABADCAAAAYQAAADCAAAAYQAAADCACAAQQAwAACAGAAAQAwgAAAGEAAAAwgAMA9C1TgCKSLscS8AAAAAElFTkSuQmCC") let base, bottom, middle, top // This is the onload effect useEffect(() => { const loadImages = async () => { base = await Jimp.read('/img/base.png') bottom = await Jimp.read('/img/bottom.png') middle = await Jimp.read('/img/middle.png') top = await Jimp.read('/img/top.png') updateIcon(h, s).then( (val) => { setIconB64(val) }) } loadImages() }, []) useEffect(() => { updateIcon(h, s).then( (string) => { console.log("Changing iconB64") setIconB64(string) }) }, [h, s]) const updateIcon = async (hue, sat) => { const base = await Jimp.read('/img/base.png') const feature = await Jimp.read('/img/feature.png') const constructed = await base .clone() .composite( feature .color([ {apply: 'hue', params: [hue]}, {apply: 'saturate', params: [sat]} ]), 0, 0, { mode: Jimp.BLEND_SOURCE_OVER } ) const string = await constructed.getBase64Async(Jimp.MIME_PNG) return string } const saveIcon = async () => { const jimpImage = await Jimp.read( Buffer.from(iconB64.split(',')[1], 'base64') ) jimpImage.getBuffer(Jimp.MIME_PNG, (err, buffer) => { fileDownload(buffer, 'snowglob.png') }) } function gradient(hue) { const offset = 210 const start = convert.hsv.hex((hue + offset) % 360, 27.3, 64.7) const end = convert.hsv.hex((hue + offset) % 360, 100, 100) const string = 'linear(to-r, #' + start + ', #' + end + ')' console.log(string) return string } return ( <>
Snowglobs Logo
Create and download a snowglob in the hue of your choice. Apologies for the 4s it takes to render a snowglob. Excellence takes time.
setH(val)} > setS(val)} > Snowglobs Logo
FAQ

What is a snowglob?

A snowglob is an abstract representation of a snow globe. A snow globe is a transparent or opaque sphere, traditionally made of glass, usually enclosing a miniaturized scene of some sort, often together with a model of a town, neighborhood, landscape or figure.



Snowglobs do not cointains a miniaturized scene.

Why are they called snowglobs?

Because the domain snowglobes.com was taken, and my domain registrar suggested snowglobs as an alternative

They look an awful lot like the LinkedIn default avatar   

That is not a question. However, any resemblence is a complete coincidence. LinkedIn default avatars are a circle overlapping an eye shape in a circle. I designed snowglobs as a circle overlapping an oval, and the image is on a square.



Furthermore, snowglobs are different colors to the LinkedIn no-profile picture avatars.



They are meant to be snowglobs.

Am I free to use my snowglob as I see fit?

You absolutely are. I hereby release all snowglob images into the public domain under the  CC0 1.0 Universal license .

Are you going to release NFTs of snowglobs?

It is on my to-do list. There will be 1800 snowglobs, each with a subtly different shade.



I just haven't gotten around to minting them yet.

Why did you build snowglobs?

I find them aesthetically pleasing.



What I certainly did not do, is design them as replacement profile pictures for LinkedIn. Please do not replace your LinkedIn profile picture with a snowglob. If you use a snowglob as a profile picture, under the terms and conditions of the site you may find that LinkedIn replaces your snowglob picture with the the LinkedIn default avatar.



And that would be terrible!
A project conceived and badly implemented by  BlockchainGandalf
) } export default HomePage