diff --git a/src/components/dots.js b/src/components/dots.js index 5372353..b34cd15 100644 --- a/src/components/dots.js +++ b/src/components/dots.js @@ -44,10 +44,13 @@ function int_range(v1, v2) { } class DotMaker { - constructor(width) { + constructor(width, height) { + console.log(width, height); this.width = width; + this.height = height; + this.wh = 0.5 * (width + height); this.cx = 0.5 * width; - this.cy = 0.5 * width; + this.cy = 0.5 * height; } dots(m, n, clip) { @@ -55,13 +58,13 @@ class DotMaker { return []; } const ps = []; - const is = int_range(-this.width, this.width / m) + const is = int_range(-this.width, this.height / m) is.map((i) => { const js = int_range(m * i + (m - n) * this.width, m * i) js.map((j) => { const x = (j - m * i) / (m - n); const y = m * (x + i); - if( !clip || (x > 0 && y > 0 && x < this.width && y < this.width) ) { + if( !clip || (x > 0 && y > 0 && x < this.width && y < this.height) ) { ps.push({i:i, j:j, x:x, y:y}); } }); @@ -78,25 +81,25 @@ class DotMaker { case "left": return maxr * (this.width - d.x) / this.width; case "down": - return maxr * d.y / this.width; + return maxr * d.y / this.height; case "up": - return maxr * (this.width - d.y) / this.width; + return maxr * (this.height - d.y) / this.height; case "right-up": - return 0.5 * maxr * (d.x + this.width - d.y) / this.width; + return 0.5 * maxr * (d.x + this.height - d.y) / this.wh; case "left-up": - return 0.5 * maxr * (this.width - d.x + this.width - d.y) / this.width; + return 0.5 * maxr * (this.width - d.x + this.height - d.y) / this.wh; case "right-down": - return 0.5 * maxr * (d.x + d.y) / this.width; + return 0.5 * maxr * (d.x + d.y) / this.wh; case "left-down": - return 0.5 * maxr * (this.width - d.x + d.y) / this.width; + return 0.5 * maxr * (this.width - d.x + d.y) / this.wh; case "out": - return 2 * maxr * distance((d.x - this.cx), (d.y - this.cy)) / this.width; + return 2 * maxr * distance((d.x - this.cx), (d.y - this.cy)) / this.wh; case "in": - return 2 * maxr * (0.5 * this.width - distance((d.x - this.cx), (d.y - this.cy))) / this.width; + return 2 * maxr * (0.5 * this.wh - distance((d.x - this.cx), (d.y - this.cy))) / this.wh; // case "hyper-out": // return 2 * maxr * Math.abs(d.x - this.cx) (d.y - this.cy)) / this.width; - // case "hyoer-in": + // case "hyper-in": // return 2 * maxr * (0.5 * this.width - distance((d.x - this.cx), (d.y - this.cy))) / this.width; case "noise": diff --git a/src/index.md b/src/index.md index bc112ba..1dd835c 100644 --- a/src/index.md +++ b/src/index.md @@ -8,11 +8,11 @@ toc: false colourful generative patterns using [d3](https://d3js.org/) and [Observable Framework](https://observablehq.com/framework/) -

v1.1.2 | by mike lynch | @mikelynch@aus.social | source

+

v1.2.0 | by mike lynch | @mikelynch@aus.social | source

-
+
-
+
```js @@ -24,18 +24,26 @@ import random from "npm:random"; import * as resvg from 'npm:@resvg/resvg-wasm'; -const CELL = 10; const MAG = 2; -const WIDTH = 20; -const HEIGHT = WIDTH; +const WIDTH = 200; +const HEIGHT = 200; -const dm = new DotMaker(WIDTH); +const cell_input = Inputs.range([5,60], {value: 10, label: "cell size"}); +const cell = view(cell_input); -const bg_input = Inputs.color({label: "background", value: d3.color("yellow").formatHex()}); + +``` + + +```js + +const bg_input = Inputs.color({ + label: "background", value: d3.color("white").formatHex() +}); const bg = view(bg_input); -const ctrl1 = new DotControls(d3.color("red").formatHex(), RADIUS_OPTS); -const ctrl2 = new DotControls(d3.color("blue").formatHex(), RADIUS_OPTS); +const ctrl1 = new DotControls(d3.color("white").formatHex(), RADIUS_OPTS); +const ctrl2 = new DotControls(d3.color("white").formatHex(), RADIUS_OPTS); const fg1 = view(ctrl1.fg); @@ -87,6 +95,8 @@ ctrl1.null_grid(); ctrl2.null_grid(); palette_input.value = PALETTES.get(rpalette); palette_input.dispatchEvent(new Event("input")); +cell_input.value = 5 + random.float() * random.float() * 55; +cell_input.dispatchEvent(new Event("input")); ctrl1.random_grid(); ctrl2.random_grid(); @@ -113,11 +123,16 @@ if( palette_fn ) { ```
-
+
```js +const width = WIDTH / cell; +const height = HEIGHT / cell; + +const dm = new DotMaker(width, height); + const dots1 = dm.dots(1 / m1, n1, false); const dots2 = dm.dots(1 / m2, n2, false); @@ -129,9 +144,9 @@ const dots2 = dm.dots(1 / m2, n2, false); const svg = d3.create("svg") - .attr("width", WIDTH * CELL * MAG) - .attr("height", HEIGHT * CELL * MAG) - .attr("viewBox", [ 0, 0, WIDTH, HEIGHT ]); + .attr("width", width * cell * MAG) + .attr("height", height * cell * MAG) + .attr("viewBox", [ 0, 0, width, height ]); svg.append("clipPath") @@ -139,8 +154,8 @@ svg.append("clipPath") .append("rect") .attr("x", 0) .attr("y", 0) - .attr("width", WIDTH) - .attr("height", HEIGHT); + .attr("width", width) + .attr("height", height); // re transitions: they should only run when updating the palette and @@ -160,8 +175,8 @@ bg_g.selectAll("rect") .join("rect") .attr("x", 0) .attr("y", 0) - .attr("width", WIDTH) - .attr("height", WIDTH) + .attr("width", width) + .attr("height", height) .attr("fill", (d) => d.bg) ; @@ -222,6 +237,7 @@ display(download(() => { ``` (PNGs made with resvg-wasm in-browser) +