Created
January 2, 2024 17:11
-
-
Save mattdesl/5d8549e614872ded7a03f5623021a0b0 to your computer and use it in GitHub Desktop.
MIT license, messy genuary2024 code... "no palettes"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import canvasSketch from "canvas-sketch"; | |
import { degToRad, linspace, radToDeg } from "canvas-sketch-util/math"; | |
import { Lch, contrastRatio } from "../util/color"; | |
import polyBool from "poly-bool"; | |
import * as random from "canvas-sketch-util/random"; | |
import { angleLerp } from "../util/angle"; | |
export const settings = { | |
suffix: random.getSeed(), | |
animate: true, | |
fps: 2, | |
playbackRate: "throttle", | |
dimensions: [2048, 2048], | |
}; | |
const background = "#e9e3d5"; | |
export const sketch = () => { | |
let { points, altColor } = generate(); | |
function generate() { | |
let attempts = 0; | |
const maxAttempts = 10000; | |
const targetMinRatio = 1.25; | |
const targetMaxRatio = 4; | |
let points, | |
altColor, | |
minRatio = 0, | |
maxRatio = 0; | |
do { | |
// const off = Math.SQRT1_2 / 4 / 2; | |
// const uvs = [ | |
// [0.5 - off, 0.5 - off], | |
// [0.5 + off, 0.5 + off], | |
// ] | |
const off = random.gaussian(0, 0.05); | |
const [ox, oy] = random.onCircle(0.1); | |
const uvs = [ | |
[0.5 - ox, 0.5 - oy], | |
[0.5 + ox, 0.5 + oy], | |
]; | |
points = uvs.map((position) => { | |
const chroma = random.range(0, 40); | |
const light = random.range(0, 100); | |
const lch = [light, chroma, random.range(0, 360)]; | |
return { | |
position, | |
lch, | |
color: Lch(...lch), | |
}; | |
}); | |
const [lchA, lchB] = points.map((c) => c.lch); | |
const l = (lchA[0] + lchB[0]) / 2; | |
const c = (lchA[1] + lchB[1]) / 2; | |
const h = radToDeg(angleLerp(degToRad(lchA[2]), degToRad(lchB[2]), 0.5)); | |
altColor = Lch(l, c, h); | |
const [colorA, colorB] = points.map((c) => c.color); | |
const r0 = contrastRatio(colorA, colorB); | |
const r1 = contrastRatio(colorA, altColor); | |
const r2 = contrastRatio(colorB, altColor); | |
const r3 = contrastRatio(colorA, background); | |
const r4 = contrastRatio(colorB, background); | |
minRatio = Math.min(r0, r1, r2, r3, r4); | |
maxRatio = Math.max(r0, r1, r2, r3, r4); | |
} while ( | |
attempts++ < maxAttempts && | |
(maxRatio > targetMaxRatio || minRatio < targetMinRatio) | |
); | |
return { points, altColor }; | |
} | |
return ({ context, width, height }) => { | |
context.fillStyle = background; | |
context.fillRect(0, 0, width, height); | |
const { points, altColor } = generate(); | |
const dim = Math.min(width, height); | |
const radius = dim * 0.25; | |
const polygons = points.map(({ position, color }, i) => { | |
const [u, v] = position; | |
const x = u * width; | |
const y = v * height; | |
const startAngle = | |
random.gaussian(0, Math.PI * 0.5) * 0 + | |
(i / points.length) * Math.PI * 0.5; | |
const steps = 4; | |
return { | |
color, | |
path: linspace(steps).map((t) => { | |
const angle = t * Math.PI * 2 + startAngle; | |
return [x + Math.cos(angle) * radius, y + Math.sin(angle) * radius]; | |
}), | |
}; | |
}); | |
const result = polyBool(polygons[0].path, polygons[1].path, "and"); | |
const shapes = [...polygons, { path: result[0], color: altColor }]; | |
shapes.forEach((shape) => { | |
context.beginPath(); | |
shape.path.forEach((p) => context.lineTo(...p)); | |
context.closePath(); | |
context.fillStyle = shape.color; | |
context.fill(); | |
}); | |
}; | |
}; | |
export default function generate(opts = {}) { | |
return canvasSketch(sketch, { | |
...settings, | |
...opts, | |
}); | |
} | |
if (typeof window["canvas-sketch-cli"] !== "undefined") { | |
generate(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment