Sporadic angular networks link disparate semi-uniform nodes.
Get occasional updates about new fonts, designs and other interesting things.
import helpers from "/scratchpad/_lib/line.asset.mjs"
import sequence from "/scratchpad/_lib/sequence.asset.mjs"
import posterize from "/scratchpad/posterize/posterize.asset.mjs"
import badge from "/scratchpad/_lib/badge.asset.mjs"
import palette from "/scratchpad/_lib/palette.asset.mjs"
import * as random from "/scratchpad/_lib/random.asset.mjs"
const dpi = window.devicePixelRatio || 1
export default (canvas) => {
const scale = dpi
canvas.width = canvas.offsetWidth * scale
canvas.height = canvas.offsetHeight * scale
const ctx = canvas.getContext("2d")
const colors = [palette.dark]
const options = {
grid: random.integer(24, 40),
iterations: random.integer(4, 8),
}
options.strokeWidth = options.grid / 2
options.blurRadius = options.strokeWidth / 8 + canvas.width / 800
const shift = random.number(options.grid)
const ow = canvas.width - options.strokeWidth * 2 - shift
const oh = canvas.height - options.strokeWidth * 2 - shift
let points = helpers
.makeGrid(ow, oh, options.grid)
.map(({ x, y, row, col }) => ({
row,
col,
x: x + random.number(shift),
y: y + random.number(shift),
}))
const iteration = (index) => [
() => {
const search = random
.shuffle([points])
.slice(0, (points.length * Math.random()) / 2)
const find = (a) => {
const fs = [
search.find((b) => a.row === b.row - 1 && a.col === b.col),
search.find((b) => a.col === b.col + 1 && a.row === b.row),
search.find((b) => a.row === b.row + 1 && a.col === b.col),
search.find((b) => a.col === b.col - 1 && a.row === b.row),
]
return (
fs[(0 + ~~count) % 4] ||
fs[(1 + ~~count) % 4] ||
fs[(2 + ~~count) % 4] ||
fs[(3 + ~~count) % 4]
)
}
let a, b
let count = 0
ctx.save()
ctx.translate(options.strokeWidth, options.strokeWidth)
ctx.beginPath()
while (search.length) {
a = search[0]
b = a
ctx.moveTo(a.x, a.y)
ctx.lineTo(b.x + 0.0001, b.y)
while ((b = find(b))) {
count += random.number()
ctx.save()
if (b.col && random.maybe(0.25)) ctx.translate(-options.grid, 0)
if (b.row && random.maybe(0.25)) ctx.translate(0, -options.grid)
ctx.lineTo(b.x, b.y)
ctx.restore()
if (b === a) break
search.splice(search.indexOf(b), 1)
}
search.splice(search.indexOf(a), 1)
}
ctx.restore()
},
() => {
const t = 1
ctx.lineCap = "round"
ctx.lineJoin = "round"
ctx.lineWidth = options.strokeWidth * t
ctx.strokeStyle = palette.dark
ctx.stroke()
ctx.lineWidth = (options.strokeWidth * t) / 3
ctx.strokeStyle = palette.canvas
ctx.stroke()
},
() => {
posterize({
ctx,
colors,
radius: options.blurRadius,
ramp: options.blurRadius * 2,
})
},
]
const steps = Array.from({ length: options.iterations }, (e, i) =>
iteration(i)
)
return sequence([steps.flat(), () => badge(ctx, { colors })])
}