Compare commits
No commits in common. "c8aad099c5e818ce5f813cf909f4fc306bc17d13" and "db222246f233c99e197ca925c549dac68d11992e" have entirely different histories.
c8aad099c5
...
db222246f2
@ -1,5 +0,0 @@
|
|||||||
# CHANGELOG.md
|
|
||||||
|
|
||||||
## v1.0.0
|
|
||||||
|
|
||||||
First deployed version
|
|
@ -1,12 +1,5 @@
|
|||||||
# poptimal
|
# poptimal
|
||||||
|
|
||||||
An experiment in using Observable to generate colourful SVG patterns
|
|
||||||
reminiscent of op art or halftone dots.
|
|
||||||
|
|
||||||
Comments, feedback via Mastodon: [Mike Lynch](https://aus.social/@mikelynch)
|
|
||||||
|
|
||||||
## Observable
|
|
||||||
|
|
||||||
This is an [Observable Framework](https://observablehq.com/framework/) app. To install the required dependencies, run:
|
This is an [Observable Framework](https://observablehq.com/framework/) app. To install the required dependencies, run:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
22
src/components/controls.js
vendored
22
src/components/controls.js
vendored
@ -16,22 +16,6 @@ function random_colour() {
|
|||||||
return d3.rgb(r, g, b).formatHex();
|
return d3.rgb(r, g, b).formatHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function random_palette() {
|
|
||||||
|
|
||||||
// monochrome
|
|
||||||
// one spot
|
|
||||||
// two spot
|
|
||||||
// RGB
|
|
||||||
// CMY
|
|
||||||
// RYB
|
|
||||||
// triad - full saturation
|
|
||||||
// triad - pastel
|
|
||||||
// trial - dusk
|
|
||||||
// random HSV
|
|
||||||
// random RGB
|
|
||||||
}
|
|
||||||
|
|
||||||
class DotControls {
|
class DotControls {
|
||||||
//
|
//
|
||||||
constructor(fg, radius_opts) {
|
constructor(fg, radius_opts) {
|
||||||
@ -39,14 +23,14 @@ class DotControls {
|
|||||||
this.fg = Inputs.color({label: "colour", value: fg});
|
this.fg = Inputs.color({label: "colour", value: fg});
|
||||||
this.m = Inputs.range([1, 5], {value: 2, step: 1, label:"m"});
|
this.m = Inputs.range([1, 5], {value: 2, step: 1, label:"m"});
|
||||||
this.n = Inputs.range([1, 5], {value: 2, step: 1, label:"n"});
|
this.n = Inputs.range([1, 5], {value: 2, step: 1, label:"n"});
|
||||||
this.r = Inputs.range([0, 0.4], {value: 0.2, step: 0.01, label: "radius"});
|
this.r = Inputs.range([0, 0.5], {value: 0.3, step: 0.01, label: "radius"});
|
||||||
this.f = Inputs.select(radius_opts, {label: "gradient", value: radius_opts[0]});
|
this.f = Inputs.select(radius_opts, {value: radius_opts[0]});
|
||||||
}
|
}
|
||||||
|
|
||||||
random_grid() {
|
random_grid() {
|
||||||
this.m.value = random.choice([1, 2, 3, 4, 5]);
|
this.m.value = random.choice([1, 2, 3, 4, 5]);
|
||||||
this.n.value = random.choice([1, 2, 3, 4, 5]);
|
this.n.value = random.choice([1, 2, 3, 4, 5]);
|
||||||
this.r.value = random.float(0, 0.4);
|
this.r.value = random.float(0, 0.5);
|
||||||
this.f.value = random.choice(this.radius_opts);
|
this.f.value = random.choice(this.radius_opts);
|
||||||
this.m.dispatchEvent(new Event("input"));
|
this.m.dispatchEvent(new Event("input"));
|
||||||
this.n.dispatchEvent(new Event("input"));
|
this.n.dispatchEvent(new Event("input"));
|
||||||
|
@ -6,10 +6,10 @@ const RADIUS_OPTS = [
|
|||||||
"left",
|
"left",
|
||||||
"up",
|
"up",
|
||||||
"down",
|
"down",
|
||||||
"right-up",
|
"RU",
|
||||||
"right-down",
|
"RD",
|
||||||
"left-up",
|
"LU",
|
||||||
"left-down",
|
"LD",
|
||||||
"in",
|
"in",
|
||||||
"out",
|
"out",
|
||||||
];
|
];
|
||||||
@ -58,13 +58,13 @@ class DotMaker {
|
|||||||
return maxr * d.y / this.width;
|
return maxr * d.y / this.width;
|
||||||
case "up":
|
case "up":
|
||||||
return maxr * (this.width - d.y) / this.width;
|
return maxr * (this.width - d.y) / this.width;
|
||||||
case "right-up":
|
case "RU":
|
||||||
return 0.5 * maxr * (d.x + this.width - d.y) / this.width;
|
return 0.5 * maxr * (d.x + this.width - d.y) / this.width;
|
||||||
case "left-up":
|
case "LU":
|
||||||
return 0.5 * maxr * (this.width - d.x + this.width - d.y) / this.width;
|
return 0.5 * maxr * (this.width - d.x + this.width - d.y) / this.width;
|
||||||
case "right-down":
|
case "RD":
|
||||||
return 0.5 * maxr * (d.x + d.y) / this.width;
|
return 0.5 * maxr * (d.x + d.y) / this.width;
|
||||||
case "left-down":
|
case "LD":
|
||||||
return 0.5 * maxr * (this.width - d.x + d.y) / this.width;
|
return 0.5 * maxr * (this.width - d.x + d.y) / this.width;
|
||||||
case "out":
|
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.width;
|
||||||
|
17
src/index.md
17
src/index.md
@ -4,8 +4,6 @@ toc: false
|
|||||||
|
|
||||||
<h1>poptimal</h1>
|
<h1>poptimal</h1>
|
||||||
|
|
||||||
<p>by <a href="https://mikelynch.org">mike lynch</a> | <a href="https://aus.social/@mikelynch">@mikelynch@aus.social</a> | <a href="https://git.tilde.town/bombinans/poptimal">source</a></p>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-2">
|
<div class="grid grid-cols-2">
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@ -22,27 +20,27 @@ const HEIGHT = WIDTH;
|
|||||||
|
|
||||||
const dm = new DotMaker(WIDTH);
|
const dm = new DotMaker(WIDTH);
|
||||||
|
|
||||||
|
|
||||||
const bg_input = Inputs.color({label: "background", value: d3.color("yellow").formatHex()});
|
const bg_input = Inputs.color({label: "background", value: d3.color("yellow").formatHex()});
|
||||||
const bg = view(bg_input);
|
const bg = view(bg_input);
|
||||||
|
|
||||||
const ctrl1 = new DotControls(d3.color("red").formatHex(), RADIUS_OPTS);
|
const ctrl1 = new DotControls(d3.color("red").formatHex(), RADIUS_OPTS);
|
||||||
const ctrl2 = new DotControls(d3.color("blue").formatHex(), RADIUS_OPTS);
|
const ctrl2 = new DotControls(d3.color("blue").formatHex(), RADIUS_OPTS);
|
||||||
|
|
||||||
|
|
||||||
const fg1 = view(ctrl1.fg)
|
const fg1 = view(ctrl1.fg)
|
||||||
const m1 = view(ctrl1.m);
|
const m1 = view(ctrl1.m);
|
||||||
const n1 = view(ctrl1.n);
|
const n1 = view(ctrl1.n);
|
||||||
const r1 = view(ctrl1.r);
|
const r1 = view(ctrl1.r);
|
||||||
const f1 = view(ctrl1.f);
|
const f1 = view(ctrl1.f);
|
||||||
|
|
||||||
|
|
||||||
const fg2 = view(ctrl2.fg)
|
const fg2 = view(ctrl2.fg)
|
||||||
const m2 = view(ctrl2.m);
|
const m2 = view(ctrl2.m);
|
||||||
const n2 = view(ctrl2.n);
|
const n2 = view(ctrl2.n);
|
||||||
const r2 = view(ctrl2.r);
|
const r2 = view(ctrl2.r);
|
||||||
const f2 = view(ctrl2.f);
|
const f2 = view(ctrl2.f);
|
||||||
|
|
||||||
const randomise_pattern = view(Inputs.button("Random dots"));
|
|
||||||
|
const randomise_pattern = view(Inputs.button("Random grids"));
|
||||||
const randomise_colours = view(Inputs.button("Random colours"));
|
const randomise_colours = view(Inputs.button("Random colours"));
|
||||||
const randomise_all = view(Inputs.button("Random all"));
|
const randomise_all = view(Inputs.button("Random all"));
|
||||||
|
|
||||||
@ -140,15 +138,6 @@ display(svg.node());
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
h1 {
|
|
||||||
font-family: helvetica, arial, sans-serif;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-family: helvetica, arial, sans-serif;
|
|
||||||
font-size: 9pt
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user