From 3e9525079c3d2791f45c9a0037f53a61863d9651 Mon Sep 17 00:00:00 2001 From: arne Date: Wed, 24 Jul 2024 22:07:33 +0200 Subject: [PATCH] Store state in URL --- src/main.ts | 68 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/src/main.ts b/src/main.ts index 71a4763..0de8e9a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,33 +9,39 @@ import { cycle, comp, range, iterator, map, mapcat, reverse, zip, filter } from // available size for a2: 420 * 594 -const sqrt2 = Math.sqrt(2) -const width_ = Math.round(420 / (document.body.clientWidth > 640 ? 1 : sqrt2)) -const height_ = Math.round(594 / (document.body.clientWidth > 640 ? 1 : sqrt2)) -const cellSize_ = 12 -const padding_ = 5 // * cellSize - +const adjustment = document.body.clientWidth > 640 ? 1 : Math.sqrt(2) // scale down the canvas on small screen const randomSeed = () => [...range(Math.ceil(Math.random() * 10))].map(_ => Math.round(Math.random())).join('') -const xSeeds_ = randomSeed() -const ySeeds_ = randomSeed() -const unit_ = 'mm' +const parseParams = (queryString: string) => { + const params = new URLSearchParams(queryString) + return { + xSeeds: params.get('xSeeds') || randomSeed(), + ySeeds: params.get('ySeeds') || randomSeed(), + cellSize: params.get('cellSize') ? Number(params.get('cellSize')) : 12, + padding: params.get('padding') ? Number(params.get('padding')) : 5, + width: params.get('width') ? Number(params.get('width')) : Math.round(420 / adjustment), + height: params.get('height') ? Number(params.get('height')) : Math.round(594 / adjustment), + unit: params.get('unit') || 'mm', + } +} + +const settings = parseParams(window.location.hash.substring(1)) // turn these into reactive values to trigger re-rendering on change -const width = reactive(width_) -const height = reactive(height_) -const unit = reactive(unit_) -const cellSize = reactive(cellSize_).map(num => Number.isNaN(num) || num < 5 ? 5 : num) // restrict cells to be at least 5 $unit -const padding = reactive(padding_) +const width = reactive(settings.width) +const height = reactive(settings.height) +const unit = reactive(settings.unit) +const cellSize = reactive(settings.cellSize).map(num => Number.isNaN(num) || num < 5 ? 5 : num) // restrict cells to be at least 5 $unit +const padding = reactive(settings.padding) const size = sync({ src: { width, height } }).map(({ width, height }) => [width, height]) const toNumber = (v: any) => typeof v === 'number' ? v : Number.parseInt(v, 10) const parsePattern = (pattern: string) => pattern.split('').map(toNumber) -const xSeeds = reactive(xSeeds_).map((pattern) => parsePattern(pattern)) -const ySeeds = reactive(ySeeds_).map((pattern) => parsePattern(pattern)) +const xSeeds = reactive(settings.xSeeds).map((pattern) => parsePattern(pattern)) +const ySeeds = reactive(settings.ySeeds).map((pattern) => parsePattern(pattern)) // const backgroundColor = getComputedStyle(document.documentElement).getPropertyValue('--background-color') const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-color') @@ -139,6 +145,32 @@ const svg = sync({ unit }) => asSvg(svgDoc({ width: `${size[0]}${unit}`, height: `${size[1]}${unit}`, viewBox: `0 0 ${size[0]} ${size[1]}` }, scene))) +// turn current settings into url hash +sync({ + src: { + size, + cellSize, + padding, + xSeeds, + ySeeds, + unit, + } +}).subscribe({ + next(settings: Record) { + const size = settings.size + delete settings.size + const serialized = { + ...settings, + width: size[0], + height: size[1], + xSeeds: settings.xSeeds.join(''), + ySeeds: settings.ySeeds.join(''), + } + const params = new URLSearchParams(serialized) + window.history.replaceState(null, '', `#${params}`) + } +}) + $compile( ["div.container", {}, ["main", {}, @@ -160,12 +192,12 @@ $compile( }), input("X Pattern: ", { type: "text", - value: xSeeds_, + value: settings.xSeeds, oninput: $input(xSeeds) }), input("Y Pattern: ", { type: "text", - value: ySeeds_, + value: settings.ySeeds, oninput: $input(ySeeds) }), input("Canvas width:", {