themer
Version:
Customizable theme creator for editors, terminals, wallpaper, and more.
103 lines (96 loc) • 3.1 kB
text/typescript
import { listOutputFiles, Template } from './index.js';
import { colorSetToVariants } from '../color-set/index.js';
import { scalePow } from 'd3-scale';
import { Perlin2 } from 'tumult';
import { source } from 'common-tags';
type Combination = {
color1: string;
color2: string;
color3: string;
};
const template: Template = {
name: 'Dot Grid wallpaper',
render: async function* (colorSet, options) {
for (const size of options.wallpaperSizes) {
const patternSize = size.w / Math.round(size.w / 36);
const scale = scalePow()
.domain([0, 1])
.range([patternSize * 0.1, patternSize * 0.95])
.exponent(2 / 3)
.clamp(true);
const perlin = new Perlin2();
const circles: string[] = [];
for (let i = 0; i < size.h; i += patternSize) {
for (let j = 0; j < size.w; j += patternSize) {
const denominator = (Math.min(size.w, size.h) / patternSize) * 21;
const rand = perlin.gen(j / denominator, i / denominator);
const radius = scale(rand) / 2;
const x = j + patternSize / 2;
const y = i + patternSize / 2;
circles.push(source`
<circle
cx="${x}"
cy="${y}"
r="${radius}"
fill="url(#overlay)"
/>
`);
}
}
const variants = colorSetToVariants(colorSet);
for (const variant of variants) {
const combinations: Combination[] = [
{
color1: variant.colors.accent3,
color2: variant.colors.accent4,
color3: variant.colors.accent6,
},
{
color1: variant.colors.accent1,
color2: variant.colors.accent2,
color3: variant.colors.accent7,
},
];
yield* combinations.map(({ color1, color2, color3 }, i) => {
const svg = source`
<svg
xmlns="http://www.w3.org/2000/svg"
width="${size.w}"
height="${size.h}"
viewBox="0 0 ${size.w} ${size.h}"
>
<defs>
<linearGradient
id="overlay"
x1="0"
y1="0"
x2="${size.w}"
y2="${size.h}"
gradientUnits="userSpaceOnUse"
>
<stop offset="0%" stop-color="${color1}" />
<stop offset="50%" stop-color="${color2}" />
<stop offset="100%" stop-color="${color3}" />
</linearGradient>
</defs>
<rect
x="0"
y="0"
width="${size.w}"
height="${size.h}"
fill="${variant.colors.shade0}"
/>
${circles}
</svg>
`;
return {
path: `${variant.title.kebab}-${size.w}x${size.h}-${i + 1}.svg`,
content: svg,
};
});
}
}
},
renderInstructions: listOutputFiles,
};
export default template;