Repeated print of fan motif with subtle variations in curve and placement.
Get occasional updates about new fonts, designs and other interesting things.
import badge from "/scratchpad/_lib/badge.asset.mjs"
import frame from "/scratchpad/_lib/frame.asset.mjs"
import posterize from "/scratchpad/posterize/posterize.asset.mjs"
import sequence from "/scratchpad/_lib/sequence.asset.mjs"
import palette from "/scratchpad/_lib/palette.asset.mjs"
import * as random from "/scratchpad/_lib/random.asset.mjs"
export default (canvas) => {
const scale = window.devicePixelRatio || 1
canvas.width = canvas.offsetWidth * scale
canvas.height = canvas.offsetHeight * scale
const ctx = canvas.getContext("2d")
const inner = Math.min(canvas.width, canvas.height)
const outer = inner / 12
ctx.fillStyle = palette.canvas
ctx.fillRect(0, 0, canvas.width, canvas.height)
return sequence([
() => arcs(ctx, outer),
() => frame(ctx, 20 * scale),
() =>
posterize({
ctx,
radius: 1,
iterations: 3,
ramp: 4.2,
overshoot: 0.6,
}),
() => badge(ctx),
])
}
const arcs = function (ctx, outer) {
const inner = 1
const rings = 12
ctx.fillStyle = palette.canvas
ctx.strokeStyle = palette.dark
let y = 0
let x = 0
let row = 0
let rWidth = random.wobble(outer, outer / 2)
let w = outer * 0.1
let lw = w / 4.5
let width, height
while (y < ctx.canvas.height + rWidth) {
y = row * (rWidth * 0.5)
x = random.wobble(-rWidth * (row % 2), rWidth * 0.25)
row++
while (x < ctx.canvas.width + rWidth) {
width = random.wobble(rWidth, w / 2)
height = random.wobble(rWidth, w)
for (let i = 0; i < rings; i++) {
for (let repeat = 0; repeat <= 2; repeat = ++repeat) {
ctx.lineWidth = random.wobble(lw, lw * 0.5)
const radius = height - (height - inner) * (i / rings)
const wf = w / 3
const cw = width - (width - inner) * (i / rings)
const cr = random.wobble(radius, w / 6)
const cx = random.wobble(x, wf)
const cy = random.wobble(y, wf)
const top = random.wobble(cy - cr * 1.1, wf)
ctx.beginPath()
ctx.moveTo(cx - cw, cy)
ctx.bezierCurveTo(
random.wobble(cx - cw, wf),
random.wobble(cy - cr * 0.4, wf),
random.wobble(cx - cw * 0.66, wf),
top,
cx,
top
)
ctx.bezierCurveTo(
random.wobble(cx + cw * 0.66, wf),
top,
random.wobble(cx + cw, wf),
random.wobble(cy - cr * 0.4, wf),
random.wobble(cx + cw, wf),
cy
)
ctx.stroke()
if (repeat === 0) {
ctx.fill()
}
if (random.maybe(0.018)) {
ctx.fillStyle = random.maybe() ? palette.dark : palette.canvas
ctx.fill()
} else {
ctx.fillStyle = palette.canvas
}
}
}
x += random.wobble(width * 2, w)
}
}
return ctx
}