Allow width and height to be dynamic
This commit is contained in:
parent
0e42f55324
commit
49ec5de609
1 changed files with 63 additions and 26 deletions
89
src/main.ts
89
src/main.ts
|
|
@ -2,32 +2,38 @@ import { line, type Line, group, translate, asSvg, svgDoc, scale, flip } from "@
|
||||||
import { vec2, type Vec2 } from "@thi.ng/vectors"
|
import { vec2, type Vec2 } from "@thi.ng/vectors"
|
||||||
import { $canvas } from "@thi.ng/rdom-canvas";
|
import { $canvas } from "@thi.ng/rdom-canvas";
|
||||||
import { reactive, sync } from "@thi.ng/rstream";
|
import { reactive, sync } from "@thi.ng/rstream";
|
||||||
import { $compile, $input } from '@thi.ng/rdom'
|
import { $compile, $input, $inputNum } from '@thi.ng/rdom'
|
||||||
import { cycle, comp, range, iterator, map, mapcat, reverse, zip } from "@thi.ng/transducers"
|
import { cycle, comp, range, iterator, map, mapcat, reverse, zip } from "@thi.ng/transducers"
|
||||||
|
|
||||||
const cellSize_ = "12"
|
// initial settings
|
||||||
const xs_ = "101110100101100"
|
|
||||||
const ys_ = "101001111001110000101"
|
|
||||||
|
|
||||||
const parsePattern = (pattern: string) => pattern.split('').map(x => Number.parseInt(x, 10))
|
// available size for a2: 420 * 594
|
||||||
|
const width_ = 420
|
||||||
|
const height_ = 594
|
||||||
|
const cellSize_ = 12
|
||||||
|
|
||||||
const xSeeds = reactive(xs_).map((pattern) => parsePattern(pattern))
|
const xSeeds_ = "101110100101100"
|
||||||
const ySeeds = reactive(ys_).map((pattern) => parsePattern(pattern))
|
const ySeeds_ = "101001111001110000101"
|
||||||
const cellSize = reactive(cellSize_).map(num => {
|
const unit_ = 'mm'
|
||||||
const next = Number.parseInt(num, 10)
|
|
||||||
return Number.isNaN(next)|| next < 5 ? 5 : next
|
// turn these into reactive values to trigger re-rendering on change
|
||||||
})
|
|
||||||
|
const width = reactive(width_)
|
||||||
|
const height = reactive(height_)
|
||||||
|
const unit = reactive(unit_)
|
||||||
|
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 cellSize = reactive(cellSize_).map(num => Number.isNaN(num) || num < 5 ? 5 : num) // restrict cells to be at least 5 $unit
|
||||||
|
|
||||||
// const backgroundColor = getComputedStyle(document.documentElement).getPropertyValue('--background-color')
|
// const backgroundColor = getComputedStyle(document.documentElement).getPropertyValue('--background-color')
|
||||||
const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-color')
|
const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-color')
|
||||||
const secondaryColor = getComputedStyle(document.documentElement).getPropertyValue('--secondary-color')
|
const secondaryColor = getComputedStyle(document.documentElement).getPropertyValue('--secondary-color')
|
||||||
|
|
||||||
// available size for a2: 420 * 594
|
|
||||||
const width = 420
|
|
||||||
const height = 594
|
|
||||||
|
|
||||||
const size = [width, height]
|
|
||||||
|
|
||||||
// some explanation for what's happening below:
|
// some explanation for what's happening below:
|
||||||
//
|
//
|
||||||
// - a coord is a position on a single axis
|
// - a coord is a position on a single axis
|
||||||
|
|
@ -71,8 +77,19 @@ const generateLines = (maxCoordOnAxis: number, maxCoordPerpendicular: number, se
|
||||||
// now we can put the functions above together based on the current settings and generate a scene to be drawn
|
// now we can put the functions above together based on the current settings and generate a scene to be drawn
|
||||||
|
|
||||||
const scene = sync({
|
const scene = sync({
|
||||||
src: { cellSize, xSeeds, ySeeds, }
|
src: {
|
||||||
}).map(({ cellSize, xSeeds, ySeeds }) => {
|
size,
|
||||||
|
cellSize,
|
||||||
|
xSeeds,
|
||||||
|
ySeeds,
|
||||||
|
}
|
||||||
|
}).map(({
|
||||||
|
size,
|
||||||
|
cellSize,
|
||||||
|
xSeeds,
|
||||||
|
ySeeds,
|
||||||
|
}) => {
|
||||||
|
const [width, height] = size
|
||||||
const minPadding = cellSize
|
const minPadding = cellSize
|
||||||
|
|
||||||
// calculate available drawing area
|
// calculate available drawing area
|
||||||
|
|
@ -85,15 +102,13 @@ const scene = sync({
|
||||||
const xLines = [...map(l => scale(l, cellSize), generateLines(yCells, xCells, cycle(ySeeds), xLineGen))]
|
const xLines = [...map(l => scale(l, cellSize), generateLines(yCells, xCells, cycle(ySeeds), xLineGen))]
|
||||||
const yLines = [...map(l => scale(l, cellSize), generateLines(xCells, yCells, cycle(xSeeds), yLineGen))]
|
const yLines = [...map(l => scale(l, cellSize), generateLines(xCells, yCells, cycle(xSeeds), yLineGen))]
|
||||||
|
|
||||||
const scene = translate(
|
return translate(
|
||||||
group(
|
group(
|
||||||
{ __background: primaryColor, stroke: secondaryColor },
|
{ __background: primaryColor, stroke: secondaryColor },
|
||||||
[...yLines, ...xLines]
|
[...yLines, ...xLines]
|
||||||
),
|
),
|
||||||
[xPadding, yPadding]
|
[xPadding, yPadding]
|
||||||
)
|
)
|
||||||
|
|
||||||
return scene
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const input = (label: string, attrs: any) =>
|
const input = (label: string, attrs: any) =>
|
||||||
|
|
@ -106,25 +121,47 @@ $compile(
|
||||||
$canvas(scene, size)],
|
$canvas(scene, size)],
|
||||||
["aside", {},
|
["aside", {},
|
||||||
["h2", {}, "Settings"],
|
["h2", {}, "Settings"],
|
||||||
|
input("Canvas width:", {
|
||||||
|
type: "number",
|
||||||
|
min: "10",
|
||||||
|
value: width.deref()!,
|
||||||
|
oninput: $inputNum(width),
|
||||||
|
}),
|
||||||
|
input("Canvas height:", {
|
||||||
|
type: "number",
|
||||||
|
min: "10",
|
||||||
|
value: height.deref()!,
|
||||||
|
oninput: $inputNum(height),
|
||||||
|
}),
|
||||||
input("Grid size: ", {
|
input("Grid size: ", {
|
||||||
type: "number",
|
type: "number",
|
||||||
min: "5",
|
min: "5",
|
||||||
value: cellSize.deref()!,
|
value: cellSize.deref()!,
|
||||||
oninput: $input(cellSize)
|
oninput: $inputNum(cellSize),
|
||||||
}),
|
}),
|
||||||
input("X Pattern: ", {
|
input("X Pattern: ", {
|
||||||
type: "text",
|
type: "text",
|
||||||
value: xs_,
|
value: xSeeds_,
|
||||||
oninput: $input(xSeeds)
|
oninput: $input(xSeeds)
|
||||||
}),
|
}),
|
||||||
input("Y Pattern: ", {
|
input("Y Pattern: ", {
|
||||||
type: "text",
|
type: "text",
|
||||||
value: ys_,
|
value: ySeeds_,
|
||||||
oninput: $input(ySeeds)
|
oninput: $input(ySeeds)
|
||||||
}),
|
}),
|
||||||
["h2", {}, "SVG Export"],
|
["h2", {}, "SVG Export"],
|
||||||
["div", {}, ["textarea", {
|
["div", {}, ["textarea", {
|
||||||
value: scene.map((scene) => asSvg(svgDoc({ viewBox: `0 0 ${size[0]} ${size[1]}` }, scene))),
|
value: sync({
|
||||||
|
src: {
|
||||||
|
scene,
|
||||||
|
size,
|
||||||
|
unit,
|
||||||
|
}
|
||||||
|
}).map(({
|
||||||
|
scene,
|
||||||
|
size,
|
||||||
|
unit
|
||||||
|
}) => asSvg(svgDoc({ width: `${size[0]}${unit}`, height: `${size[1]}${unit}`, viewBox: `0 0 ${size[0]} ${size[1]}` }, scene))),
|
||||||
cols: 80,
|
cols: 80,
|
||||||
rows: 20
|
rows: 20
|
||||||
}]]]]
|
}]]]]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue