Get occasional updates about new fonts, designs and other interesting things.
import * as random from "/scratchpad/_lib/random.asset.mjs"
import posterize from "/scratchpad/posterize/posterize.asset.mjs"
const repeat = (length, fn) => {
Array.from({ length }).forEach((t, i) => {
fn(i, length)
})
}
const shape = (ctx, r, dir = 1) => {
const x = random.wobble(4)
const y = random.wobble(4)
let r1 = r * random.number(1, 1.2)
let r2 = r * random.number(0.7, 1)
let variance = Math.abs(r2 / r1)
variance = Math.min(variance, 1 / variance)
if (variance < 0.2) {
ctx.arc(0, 0, Math.abs(r2), 0, Math.PI * 2, dir < 0)
} else {
let points = random.integer(8, 19)
for (let i = 0; i < points; i++) {
const angle =
random.number(Math.PI) +
((i * 2 * Math.PI) / (points % 2 == 0 ? points : points - 1)) * dir
r = i % 2 === 0 ? r1 : r2
ctx[i === 0 ? "moveTo" : "lineTo"](
x + r * Math.cos(angle),
y + r * Math.sin(angle)
)
}
}
}
const palette = () => ({
white: "white",
yolk: [random.integer(220, 225), random.integer(128, 158), 0].reduce(
(m, d) => m + ("0" + d.toString(16)).slice(-2),
"#"
),
})
export default (ctx, dimensions, smooth = true) => {
const { x, y, width, height } = dimensions
const size = Math.min(width, height)
const colors = palette()
ctx.save()
ctx.translate(x + width / 2, y + height / 2)
ctx.beginPath()
repeat(random.integer(50, 70), (i, length) => {
const r = (size * 0.4 * (i + 1)) / length
shape(ctx, r, i % 2 ? 1 : -1)
})
ctx.fillStyle = colors.white
ctx.fill()
ctx.beginPath()
repeat(random.integer(20, 50), (i, length) => {
const r = ((size / 2) * 0.4 * (i + 1)) / length
shape(ctx, r, i % 2 ? 1 : -1)
})
ctx.fillStyle = colors.yolk
ctx.fill()
if (smooth) {
posterize({
ctx,
radius: size * 0.04,
iterations: 3,
ramp: 300,
colors: [colors.yolk, colors.white],
overshoot: 1,
x,
y,
width,
height,
})
}
ctx.restore()
return { colors }
}