diff --git a/docs/chapters/control/lerp.js b/docs/chapters/control/lerp.js
index 68ebc354..553b110e 100644
--- a/docs/chapters/control/lerp.js
+++ b/docs/chapters/control/lerp.js
@@ -5,21 +5,23 @@ setup() {
const degree = this.parameters.degree ?? 3;
if (degree === 3) {
- this.f = [
+ // there are three interpolation functions for quadratic curves
+ this.interpolationFunctions = [
t => ({ x: t * w, y: h * (1-t) ** 2 }),
t => ({ x: t * w, y: h * 2 * (1-t) * t }),
t => ({ x: t * w, y: h * t ** 2 })
];
} else if (degree === 4) {
- this.f = [
+ // there are four interpolation functions for cubic curves
+ this.interpolationFunctions = [
t => ({ x: t * w, y: h * (1-t) ** 3 }),
t => ({ x: t * w, y: h * 3 * (1-t) ** 2 * t }),
t => ({ x: t * w, y: h * 3 * (1-t) * t ** 2 }),
t => ({ x: t * w, y: h * t ** 3})
];
} else {
- this.triangle = [[1], [1,1]];
- this.f = [...new Array(degree + 1)].map((_,i) => {
+ // there are many interpolations functions for more complex curves
+ this.interpolationFunctions = [...new Array(degree + 1)].map((_,i) => {
return t => ({
x: t * w,
y: h * binomial(degree,i) * (1-t) ** (degree-i) * t ** (i)
@@ -27,7 +29,11 @@ setup() {
});
}
- this.s = this.f.map(f => plot(f, 0, 1, degree*5) );
+ // Build the graph for each interpolation function by plotting them,
+ // and capturing the resulting Shape object that yields. We'll draw
+ // those in the draw() function.
+ this.shapes = this.interpolationFunctions.map(f => plot(f, 0, 1, degree*5) );
+
setSlider(`.slide-control`, `position`, 0)
}
@@ -36,39 +42,48 @@ draw() {
setFill(`black`);
setStroke(`black`);
+ // In order to plot things nicely, lets scale
+ // down, and plot things in a graph:
scale(0.8, 0.9);
translate(40,20);
drawAxes(`t`, 0, 1, `S`, `0%`, `100%`);
noFill();
- this.s.forEach((s,i) => {
+ // draw each of the function plots we built in setup()
+ this.shapes.forEach((shape,i) => {
+ // first, draw that plot's mid-line
setStroke(randomColor(0.2));
line(
- i/(this.s.length-1) * this.width, 0,
- i/(this.s.length-1) * this.width, this.height
+ i/(this.shapes.length-1) * this.width, 0,
+ i/(this.shapes.length-1) * this.width, this.height
)
+ // and then draw the plot itself
setStroke(randomColor(1.0, false ));
- drawShape(s);
+ drawShape(shape);
})
+ // depending on the slider, also highlight all values at t=...
this.drawHighlight();
}
drawHighlight() {
const t = this.position;
+ // 0 and 1 are not meaningful to look at. They're just "100% start/end"
if (t===0) return;
if (t===1) return;
+ // draw a little highlighting bar that runs frop top to bottom
noStroke();
setFill(`rgba(255,0,0,0.3)`);
rect(t*this.width - 2, 0, 5, this.height);
- const p = this.f.map(f => f(t));
-
+ // then calculate each interpolation point for our `t` value
+ // and draw it, with a label that says how much it contributes
+ const points = this.interpolationFunctions.map(f => f(t));
setFill(`black`);
- p.forEach(p => {
+ points.forEach(p => {
circle(p.x, p.y, 3);
text(`${ round(100 * p.y/this.height) }%`, p.x + 10, p.y);
});
diff --git a/docs/chapters/decasteljau/decasteljau.js b/docs/chapters/decasteljau/decasteljau.js
index 35cdb037..d56cbac8 100644
--- a/docs/chapters/decasteljau/decasteljau.js
+++ b/docs/chapters/decasteljau/decasteljau.js
@@ -1,34 +1,80 @@
+let curve;
+
setup() {
- this.curve = new Bezier(this, 90, 200, 25, 100, 220, 40, 210, 240);
- setMovable(this.curve.points);
+ curve = new Bezier(this, 90, 200, 25, 100, 220, 40, 210, 240);
+ setMovable(curve.points);
setSlider(`.slide-control`, `position`, 0);
}
draw() {
clear();
- const curve = this.curve;
curve.drawSkeleton();
curve.drawCurve();
+ noFill();
setStroke("rgb(200,100,100)");
- let t = this.position;
+ const t = this.position;
if (0 < t && t < 1) {
- curve.drawStruts(t);
+ this.drawStruts(t);
}
curve.drawPoints();
if (0 < t && t < 1) {
- let p = curve.get(t);
+ const p = curve.get(t);
circle(p.x, p.y, 5);
- let perc = (t*100)|0;
- let rt = perc/100;
+ const perc = (t*100)|0;
+ const rt = perc/100;
text(`Sequential interpolation for ${perc}% (t=${rt})`, 10, 15);
}
}
+drawStruts(t) {
+ // get all the "de Casteljau" points
+ const p = curve.getStrutPoints(t);
+
+ // and then draw them
+ let s = curve.points.length;
+ let n = curve.points.length;
+ while (--n > 1) {
+ start();
+ for (let i = 0; i < n; i++) {
+ let pt = p[s + i];
+ vertex(pt.x, pt.y);
+ circle(pt.x, pt.y, 5);
+ }
+ end();
+ s += n;
+ }
+}
+
+getStrutPoints(t) {
+ const mt = 1 - t;
+
+ // run de Casteljau's algorithm, starting with the base points
+ const points = curve.points.map((p) => new Vector(p));
+
+ let s = 0;
+ let n = p.length + 1;
+
+ // Every iteration will interpolate between `n` points,
+ // as well as decrease that `n` by one. So 4 points yield
+ // 3 new points, which yield 2 new points, which yields 1
+ // final point that is our on-curve point for `t`
+ while (--n > 1) {
+ let list = points.slice(s, s + n);
+ for (let i = 0, e = list.length - 1; i < e; i++) {
+ let pt = list[i + 1].subtract(list[i + 1].subtract(list[i]).scale(mt));
+ points.push(pt);
+ }
+ s += n;
+ }
+
+ return points;
+}
+
onMouseMove() {
redraw();
}
diff --git a/docs/chapters/explanation/circle.js b/docs/chapters/explanation/circle.js
index 11ede153..09f451ac 100644
--- a/docs/chapters/explanation/circle.js
+++ b/docs/chapters/explanation/circle.js
@@ -8,29 +8,36 @@ draw() {
const dim = this.height,
w = dim,
h = dim,
+ // midpoints
w2 = w/2,
h2 = h/2,
- w4 = w2/2,
- h4 = h2/2;
+ // quarterpoints
+ q = dim/4;
+ // draw axes with (0,0) in the middle of the graphic
setStroke(`black`);
line(0, h2, w, h2);
line(w2, 0, w2, h);
- var offset = {x:w2, y:h2};
-
- for(let t=0, p, mod; t<=this.steps; t+=0.1) {
+ for(let t=0, p, step=0.1; t<=this.steps; t+=step) {
+ // create a point at distance 'q' from the midpoint
p = {
- x: w2 + w4 * cos(t),
- y: h2 + h4 * sin(t)
+ x: w2 + q * cos(t),
+ y: h2 + q * sin(t)
};
+
+ // and draw it.
circle(p.x, p.y, 1);
- mod = t % 1;
- if(mod >= 0.9) {
- text(`t = ${ round(t) }`,
- w2 + 1.25 * w4 * cos(t) - 10,
- h2 + 1.25 * h4 * sin(t) + 10
+ // then add a text label too, but only "near" each integer
+ // step of `t`. Since we're using floating point numbers,
+ // we can't rely on x * 1/x to actually be x (if only life
+ // were that easy) so we need to check whether `t` is "near"
+ // an integer value instead.
+ if(approx(t % 1, 1, step)) {
+ text(`t = ${round(t)}`,
+ w2 + 1.25 * q * cos(t) - 10,
+ h2 + 1.25 * q * sin(t) + 10
);
circle(p.x, p.y, 2);
}
diff --git a/docs/chapters/extended/extended.js b/docs/chapters/extended/extended.js
index ab8118bd..17a99fe8 100644
--- a/docs/chapters/extended/extended.js
+++ b/docs/chapters/extended/extended.js
@@ -8,20 +8,27 @@ setup() {
draw() {
clear();
- curve.drawCurve();
- curve.drawSkeleton();
- let step=0.05, min=-10, max=10;
+ // let's draw the curve from -10 to 10, instead of 0 to 1
+ setStroke(`skyblue`);
+ let min=-10, max=10, step=0.05;
+
+ // calculate the very first point
let pt = curve.get(min - step), pn;
- setStroke(`skyblue`);
- for (let t=min; t<=step; t+=step) {
+ // then draw the section from -10 to 0
+ for (let t=min; t circle(p.x, p.y, 3));
+
noFill();
setStroke(`red`);
circle(p.x, p.y, 3);
+
setFill(`black`)
text(`The ${halfLabel} half`, 10, 15);
}
diff --git a/docs/chapters/weightcontrol/rational.js b/docs/chapters/weightcontrol/rational.js
index 3814c902..a015a507 100644
--- a/docs/chapters/weightcontrol/rational.js
+++ b/docs/chapters/weightcontrol/rational.js
@@ -3,9 +3,15 @@ let curve, ratios=[1, 1, 1, 1];
setup() {
curve = Bezier.defaultCubic(this);
setMovable(curve.points);
- curve.points.forEach((p,i) => {
+ for (let i=0; i<4; i++) {
+ // Set up a slider, but in a way that does not tie it to a variable
+ // that is exposed through `this`, because we want to store its value
+ // in the "ratios" array we already declared globally.
+ //
+ // To make that happen, we tell the slider logic that it should be
+ // calling the setRatio function instead when the slider moves.
setSlider(`.ratio-${i+1}`, `!ratio-${i+1}`, 1, v => this.setRatio(i,v))
- });
+ }
}
setRatio(i, v) {
diff --git a/docs/images/chapters/arclength/56533f47e73ad9fea08fa9bb3f597d49.png b/docs/images/chapters/arclength/56533f47e73ad9fea08fa9bb3f597d49.png
index 325512d2..a1586887 100644
Binary files a/docs/images/chapters/arclength/56533f47e73ad9fea08fa9bb3f597d49.png and b/docs/images/chapters/arclength/56533f47e73ad9fea08fa9bb3f597d49.png differ
diff --git a/docs/images/chapters/arclength/5ce02cbdbc47585c588f2656d5161a32.png b/docs/images/chapters/arclength/5ce02cbdbc47585c588f2656d5161a32.png
index 5baa0223..411514d2 100644
Binary files a/docs/images/chapters/arclength/5ce02cbdbc47585c588f2656d5161a32.png and b/docs/images/chapters/arclength/5ce02cbdbc47585c588f2656d5161a32.png differ
diff --git a/docs/images/chapters/arclength/fe2663b205d14c157a5a02bfbbd55987.png b/docs/images/chapters/arclength/fe2663b205d14c157a5a02bfbbd55987.png
index fe3bac3a..54c76271 100644
Binary files a/docs/images/chapters/arclength/fe2663b205d14c157a5a02bfbbd55987.png and b/docs/images/chapters/arclength/fe2663b205d14c157a5a02bfbbd55987.png differ
diff --git a/docs/images/chapters/circles/5801de8227960faa9bcbae578f78c2a3.png b/docs/images/chapters/circles/5801de8227960faa9bcbae578f78c2a3.png
deleted file mode 100644
index 7de43a50..00000000
Binary files a/docs/images/chapters/circles/5801de8227960faa9bcbae578f78c2a3.png and /dev/null differ
diff --git a/docs/images/chapters/circles/8c2eb77bfd11231393a77e72f03ebe83.png b/docs/images/chapters/circles/8c2eb77bfd11231393a77e72f03ebe83.png
deleted file mode 100644
index dff2fb43..00000000
Binary files a/docs/images/chapters/circles/8c2eb77bfd11231393a77e72f03ebe83.png and /dev/null differ
diff --git a/docs/images/chapters/circles_cubic/331f3f89b1dac9e1e60f61c5d95f9e5b.png b/docs/images/chapters/circles_cubic/331f3f89b1dac9e1e60f61c5d95f9e5b.png
deleted file mode 100644
index 697c2f31..00000000
Binary files a/docs/images/chapters/circles_cubic/331f3f89b1dac9e1e60f61c5d95f9e5b.png and /dev/null differ
diff --git a/docs/images/chapters/circles_cubic/da768b84c91262bab8ab36f895e8569b.png b/docs/images/chapters/circles_cubic/da768b84c91262bab8ab36f895e8569b.png
deleted file mode 100644
index 53a76dc3..00000000
Binary files a/docs/images/chapters/circles_cubic/da768b84c91262bab8ab36f895e8569b.png and /dev/null differ
diff --git a/docs/images/chapters/control/fca18b2602929f80e68d8964832f0f44.png b/docs/images/chapters/control/4b206c16ccf8a06a0834fe9e5254560c.png
similarity index 100%
rename from docs/images/chapters/control/fca18b2602929f80e68d8964832f0f44.png
rename to docs/images/chapters/control/4b206c16ccf8a06a0834fe9e5254560c.png
diff --git a/docs/images/chapters/control/989f4ca49d7099802cc0345dbeddca8c.png b/docs/images/chapters/control/be82cd31c4892a8f0582b1b5285231d9.png
similarity index 100%
rename from docs/images/chapters/control/989f4ca49d7099802cc0345dbeddca8c.png
rename to docs/images/chapters/control/be82cd31c4892a8f0582b1b5285231d9.png
diff --git a/docs/images/chapters/control/2a0635829051977b265b64ef204f718e.png b/docs/images/chapters/control/f700cd59e6021b0e06b819105ec931da.png
similarity index 100%
rename from docs/images/chapters/control/2a0635829051977b265b64ef204f718e.png
rename to docs/images/chapters/control/f700cd59e6021b0e06b819105ec931da.png
diff --git a/docs/images/chapters/decasteljau/715d1d2eecc762d6bc1470954b145018.png b/docs/images/chapters/decasteljau/df92f529841f39decf9ad62b0967855a.png
similarity index 100%
rename from docs/images/chapters/decasteljau/715d1d2eecc762d6bc1470954b145018.png
rename to docs/images/chapters/decasteljau/df92f529841f39decf9ad62b0967855a.png
diff --git a/docs/images/chapters/explanation/6d2f915735ebdc05e42c0ea7adc85343.png b/docs/images/chapters/explanation/959762e39ae32407e914a687d804ff3a.png
similarity index 100%
rename from docs/images/chapters/explanation/6d2f915735ebdc05e42c0ea7adc85343.png
rename to docs/images/chapters/explanation/959762e39ae32407e914a687d804ff3a.png
diff --git a/docs/images/chapters/extended/2d17acb381ebdd28f0ff43be00d723c4.png b/docs/images/chapters/extended/2d17acb381ebdd28f0ff43be00d723c4.png
new file mode 100644
index 00000000..6613240a
Binary files /dev/null and b/docs/images/chapters/extended/2d17acb381ebdd28f0ff43be00d723c4.png differ
diff --git a/docs/images/chapters/extended/37948bde4bf0d25bde85f172bf55b9fb.png b/docs/images/chapters/extended/37948bde4bf0d25bde85f172bf55b9fb.png
new file mode 100644
index 00000000..a714c4c5
Binary files /dev/null and b/docs/images/chapters/extended/37948bde4bf0d25bde85f172bf55b9fb.png differ
diff --git a/docs/images/chapters/extended/391a61142c56b79260680aefb08cd9c4.png b/docs/images/chapters/extended/391a61142c56b79260680aefb08cd9c4.png
deleted file mode 100644
index 75fd1f21..00000000
Binary files a/docs/images/chapters/extended/391a61142c56b79260680aefb08cd9c4.png and /dev/null differ
diff --git a/docs/images/chapters/extended/baeceec6e1587794b8b275a90d5d85e9.png b/docs/images/chapters/extended/baeceec6e1587794b8b275a90d5d85e9.png
deleted file mode 100644
index 8cec37fb..00000000
Binary files a/docs/images/chapters/extended/baeceec6e1587794b8b275a90d5d85e9.png and /dev/null differ
diff --git a/docs/images/chapters/flattening/e2bb7113d5cda2e3fd29bbc54fbe8841.png b/docs/images/chapters/flattening/0e0e4a2ee46bd89bcfde9f75cfe43292.png
similarity index 100%
rename from docs/images/chapters/flattening/e2bb7113d5cda2e3fd29bbc54fbe8841.png
rename to docs/images/chapters/flattening/0e0e4a2ee46bd89bcfde9f75cfe43292.png
diff --git a/docs/images/chapters/flattening/3deec756c96e53127cd1d615c61043ae.png b/docs/images/chapters/flattening/6813bfc608aea11df1dda444b9f18123.png
similarity index 100%
rename from docs/images/chapters/flattening/3deec756c96e53127cd1d615c61043ae.png
rename to docs/images/chapters/flattening/6813bfc608aea11df1dda444b9f18123.png
diff --git a/docs/images/chapters/reordering/c37918c649befad06de255a6415faf29.png b/docs/images/chapters/reordering/c37918c649befad06de255a6415faf29.png
index 35fbe9ba..253c3882 100644
Binary files a/docs/images/chapters/reordering/c37918c649befad06de255a6415faf29.png and b/docs/images/chapters/reordering/c37918c649befad06de255a6415faf29.png differ
diff --git a/docs/images/chapters/splitting/891133c5f0e140b8c7e179af04e497e0.png b/docs/images/chapters/splitting/fce5eb16dfcd103797c5e17bd77f1437.png
similarity index 100%
rename from docs/images/chapters/splitting/891133c5f0e140b8c7e179af04e497e0.png
rename to docs/images/chapters/splitting/fce5eb16dfcd103797c5e17bd77f1437.png
diff --git a/docs/images/chapters/weightcontrol/be18e8119472af796329f3e2159bdf94.png b/docs/images/chapters/weightcontrol/3d71e2b9373684eebcb0dc8563f70b18.png
similarity index 100%
rename from docs/images/chapters/weightcontrol/be18e8119472af796329f3e2159bdf94.png
rename to docs/images/chapters/weightcontrol/3d71e2b9373684eebcb0dc8563f70b18.png
diff --git a/docs/index.html b/docs/index.html
index 13226911..eb0e74e3 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -31,7 +31,7 @@
-
+
@@ -581,7 +581,7 @@
Scripts are disabled. Showing fallback image.
-
+
@@ -749,7 +749,7 @@ function Bezier(3,t):
Scripts are disabled. Showing fallback image.
-
+
@@ -758,7 +758,7 @@ function Bezier(3,t):
Scripts are disabled. Showing fallback image.
-
+
@@ -767,7 +767,7 @@ function Bezier(3,t):
Scripts are disabled. Showing fallback image.
-
+
@@ -879,7 +879,7 @@ function Bezier(3,t,w[]):
Scripts are disabled. Showing fallback image.
-
+
@@ -976,7 +976,7 @@ function RationalBezier(3,t,w[],r[]):
>
Scripts are disabled. Showing fallback image.
-
+
@@ -989,7 +989,7 @@ function RationalBezier(3,t,w[],r[]):
>
Scripts are disabled. Showing fallback image.
-
+
@@ -1093,7 +1093,7 @@ function RationalBezier(3,t,w[],r[]):
>
Scripts are disabled. Showing fallback image.
-
+
@@ -1157,7 +1157,7 @@ function RationalBezier(3,t,w[],r[]):
>
Scripts are disabled. Showing fallback image.
-
+
@@ -1166,7 +1166,7 @@ function RationalBezier(3,t,w[],r[]):
Scripts are disabled. Showing fallback image.
-
+
@@ -1213,7 +1213,7 @@ function RationalBezier(3,t,w[],r[]):
Scripts are disabled. Showing fallback image.
-
+
diff --git a/docs/ja-JP/index.html b/docs/ja-JP/index.html
index ae9c6ec7..84bc056f 100644
--- a/docs/ja-JP/index.html
+++ b/docs/ja-JP/index.html
@@ -33,7 +33,7 @@
-
+
@@ -528,7 +528,7 @@
Scripts are disabled. Showing fallback image.
-
+
@@ -670,7 +670,7 @@ function Bezier(3,t):
Scripts are disabled. Showing fallback image.
-
+
@@ -679,7 +679,7 @@ function Bezier(3,t):
Scripts are disabled. Showing fallback image.
-
+
@@ -688,7 +688,7 @@ function Bezier(3,t):
Scripts are disabled. Showing fallback image.
-
+
@@ -787,7 +787,7 @@ function Bezier(3,t,w[]):
Scripts are disabled. Showing fallback image.
-
+
@@ -868,14 +868,14 @@ function RationalBezier(3,t,w[],r[]):
Scripts are disabled. Showing fallback image.
-
+ Scripts are disabled. Showing fallback image.
-
+
@@ -965,7 +965,7 @@ function RationalBezier(3,t,w[],r[]):
Scripts are disabled. Showing fallback image.
-
+
@@ -1015,7 +1015,7 @@ function RationalBezier(3,t,w[],r[]):
Scripts are disabled. Showing fallback image.
-
+
@@ -1024,7 +1024,7 @@ function RationalBezier(3,t,w[],r[]):
Scripts are disabled. Showing fallback image.
-
+
@@ -1066,7 +1066,7 @@ function RationalBezier(3,t,w[],r[]):
Scripts are disabled. Showing fallback image.
-
+
diff --git a/docs/js/custom-element/api/README.md b/docs/js/custom-element/api/README.md
index 911457ae..3fa16a5f 100644
--- a/docs/js/custom-element/api/README.md
+++ b/docs/js/custom-element/api/README.md
@@ -14,13 +14,17 @@ draw() {
All code starts at `setup()`, automatically calling `draw()` after setup has been completed. Standard JS scoping applies, so any variable declared outside of `setup`/`draw` will be a "global" variable.
-## User Events
+Note that neither of these functions are _required_: without a `setup()` function the code will just jump straight to `draw()`, and without a `draw()` function the code will simply not draw anything beyond the initial empty canvas.
+
+## User-initiated events
+
+### Touch/mouse events
Graphics code can react to touch/mouse, which can be handled using:
- `onMouseDown()` triggered by mouse/touch start events.
- `onMouseUp()` triggered by mouse/touch end events.
-- `onMouseMose()` triggered by moving the mouse/your finger.
+- `onMouseMove()` triggered by moving the mouse/your finger.
Mouse event data can be accessed via the `this.cursor` property, which encodes:
@@ -37,6 +41,35 @@ Mouse event data can be accessed via the `this.cursor` property, which encodes:
}
```
+#### Example
+
+```js
+setup() {
+ this.defaultBgColor = this.bgColor = `green`;
+}
+
+draw() {
+ clear(this.bgColor);
+}
+
+onMouseDown() {
+ this.bgColor = `blue`;
+ redraw();
+}
+
+onMouseMove() {
+ this.bgColor = `red`;
+ redraw();
+}
+
+onMouseUp() {
+ this.bgColor = this.defaultBgColor;
+ redraw();
+}
+```
+
+### Keyboard events
+
Graphics code can also react to keyboard events, although this is a great way to make sure your code won't work for mobile devices, so it's better to use range sliders to keep things accessible. That said, they can be handled using:
- `onKeyDown()` triggered by pressing a key
@@ -54,15 +87,45 @@ Additionally, the `this.keyboard` property can be consulted for named keys to se
```js
draw() {
- if (this.keyboard[`ArrowUp`]) {
- ...
+ if (this.keyboard[`w`] && this.keyboard[`d`]) {
+ // move up-left
}
}
```
+#### Example
+
+```js
+setup() {
+ this.y = this.height/2;
+}
+
+draw() {
+ clear();
+ setColor(`black`);
+ rect(0, this.y-1, this.width, 3);
+}
+
+onKeyDown() {
+ const key = this.keyboard.currentKey;
+ if (key === `ArrowUp`) {
+ y -= 5
+ }
+ if (key === `ArrowDown`) {
+ y += 5;
+ }
+ y = constrain(y, 0, this.height);
+ redraw();
+}
+```
+
## Controllable parameters
-Graphics code can be passed external values from HTML using data attributes:
+Graphics code can be provided with outside values in two different ways.
+
+### Using fixed startup parameters
+
+Graphics code can be passed fixed values from HTML using data attributes:
```html
@@ -74,21 +137,38 @@ which can be access on the code side using
this.parameters.propname;
```
-Additionally, graphics code has special functions for range values, either directly in code:
+Note that `this.parameters` is a protected object. Properties of the parameters object can be updated by your code, but you cannot reassign `this.parameters` itself.
+
+
+### Using dynamic value sliders
+
+Graphics code has also be provided with dynamic values by using range sliders. There are two ways to do this: purely in code, or by tying the graphics code to HTML sliders.
+
+#### In code
+
+If sliders may be dynamically required, the `addSlider` function can be used:
```js
setup() {
- // name, min, max, step, initial value
addSlider(`rangeValue`, 0, 1, 0.001, 0.5);
}
draw() {
- // values defined through sliders become accessible on `this`:
console.log(this.rangeValue);
}
```
-Alternatively, they can be hooked into a predefined slider:
+Its function signature is `addSlider(property name, min, max, step, initial value)`, in which the arguments represent:
+
+- `property name` a propertyname string that may start with `!`. If no `!` is used, the property name should follow the rules for variable names, as the property will be exposed as `this.propertyname` (e.g. is you use `rangeValue`, then `this.rangeValue` will exis and be kept up to date by the slider logic). If `!` is used, no `this.propertyname` will be be set up for use in your code. Regardless of whether `!` is used or not, the property name will also be displayed in the slider's UI.
+- `min` the minimum numerical value this variable will be able to take on
+- `max` the meximum numerical value this variable will be able to take on
+- `step` the value increase/decrease per step of the slider.
+- `initial value` the value that the associated variable will be assigned as part of the `addSlider` call.
+
+#### From HTML
+
+You can also "presupply" a graphic with sliders, if you know your graphic has a fixed number of dynamic variables. This uses the standard HTML `` element:
```html
@@ -96,11 +176,10 @@ Alternatively, they can be hooked into a predefined slider:
```
-using the `setSlider` function:
+With the graphic code using `setSlider` with a query selector to find your slider element and tie it to a variable:
```js
setup() {
- // local query selector, name, initial value
setSlider(`.my-slider`, `rangeValue`, 0.5);
}
@@ -109,6 +188,17 @@ draw() {
}
```
+Its function signature is `setSlider(query selector, property name, initial value)`, in which the arguments represent:
+
+- `query select` a CSS query selector for finding the right slider in your `` tree. If you only have one slider then this query selector can simply be `input[type=range]`, but if you have multiple sliders it's a better idea to give each slider a CSS class that can be used to indentify it.
+- `property name` a propertyname string that may start with `!`. If no `!` is used, the property name should follow the rules for variable names, as the property will be exposed as `this.propertyname` (e.g. is you use `rangeValue`, then `this.rangeValue` will exis and be kept up to date by the slider logic). If `!` is used, no `this.propertyname` will be be set up for use in your code. Regardless of whether `!` is used or not, the property name will also be displayed in the slider's UI.
+- `initial value` the value that the associated variable will be assigned as part of the `addSlider` call.
+
+Note that while it might seem that `` elements can be made fully self-descriptive for both the property name (using the `name` attribute) and initial value (using the `value` attribute), this code still needs to do the right thing even in the absence of an HTML page, and so the property name and initial value are explicitly required.
+
+**warning:** if you try to set up a slider for a property name that you have already defined, the code will throw a runtime error.
+
+
## Movable points
An important part of the Graphics API is showing shapes that are controlled or defined by coordinates, and as there are special functions for marking points as "movable" - that is, these points can be click/touch-dragged around a graphic. To fascilitate this, the following functions can be used:
@@ -117,12 +207,12 @@ An important part of the Graphics API is showing shapes that are controlled or d
- `resetMovable()` will clear the list of movable points.
- `resetMovable(points, ...)` is the same as calling `resetMovable()` followed by `setMovable(points, ...)`.
+
## The API
The following is the list of API functions that can be used to draw... whatever you like, really.
-
-### gGobal constants
+### Global constants
- `PI` 3.14159265358979
- `TAU` 6.28318530717958
@@ -247,7 +337,7 @@ In addition to transformations, there are also two functions to allow you to map
- `drawShape(...shapes)` draw one or more saved full shapes (see below)
- `image(img, x = 0, y = 0, w = auto, h = auto)` draw an image at some (x,y) coordinate, defaulting to (0,0), scaled to some width and height, defaulting to the native image dimensions
- `line(x1, y1, x2, y2)` draw a line from (x1,y1) to (x2,y2)
-- `plot(fn, start = 0, end = 1, steps = 24, xscale = 1, yscale = 1)` plot a function defined by `fn` (which must take a single numerical input, and output an object of the form `{x:..., y:...}`) for inputs in the interval [start,end], at a resolution of `steps` steps, with the resulting values scaled by `xscale` horizontally, and `yscale` vertically.
+- `plot(fn, start = 0, end = 1, steps = 24, xscale = 1, yscale = 1)` plot a function defined by `fn` (which must take a single numerical input, and output an object of the form `{x:..., y:...}`) for inputs in the interval [start,end], at a resolution of `steps` steps, with the resulting values scaled by `xscale` horizontally, and `yscale` vertically. This function returns the plot as a `Shape` for later reuse.
- `point(x, y)` draw a single point at (x,y)
- `rect(x, y, w, h)` draw a rectangle from (x,y) with width `w` and height `h`
- `redraw()` triggers a new draw loop. Use this instead of calling `draw()` directly when you wish to draw a new frame as part of event handling.
@@ -263,7 +353,7 @@ In addition to transformations, there are also two functions to allow you to map
- `saveShape()` returns the current shape for later reuse
-## Built in object types
+## Built-in object types
### Shape
diff --git a/docs/js/custom-element/api/base-api.js b/docs/js/custom-element/api/base-api.js
index 721f3fd7..3206f4b2 100644
--- a/docs/js/custom-element/api/base-api.js
+++ b/docs/js/custom-element/api/base-api.js
@@ -53,23 +53,27 @@ class BaseAPI {
this.dataset = {};
}
}
- this.parameters = Object.fromEntries(
- Object.entries(this.dataset)
- .map((pair) => {
- let name = pair[0];
- let v = pair[1];
- if (v === `null` || v === `undefined`) return [];
- if (v === `true`) return [name, true];
- else if (v === `false`) return [name, false];
- else {
- let d = parseFloat(v);
- // Use == to evaluate "is this a string number"
- if (v == d) return [name, d];
- }
- return [name, v];
- })
- .filter((v) => v.length)
- );
+ Object.defineProperty(this, `parameters`, {
+ writable: false,
+ configurable: false,
+ value: Object.fromEntries(
+ Object.entries(this.dataset)
+ .map((pair) => {
+ let name = pair[0];
+ let v = pair[1];
+ if (v === `null` || v === `undefined`) return [];
+ if (v === `true`) return [name, true];
+ else if (v === `false`) return [name, false];
+ else {
+ let d = parseFloat(v);
+ // Use == to evaluate "is this a string number"
+ if (v == d) return [name, d];
+ }
+ return [name, v];
+ })
+ .filter((v) => v.length)
+ ),
+ });
this.addListeners();
this.setSize(width, height);
this.currentPoint = false;
diff --git a/docs/js/custom-element/api/graphics-api.js b/docs/js/custom-element/api/graphics-api.js
index 00dff793..8a5f3c54 100644
--- a/docs/js/custom-element/api/graphics-api.js
+++ b/docs/js/custom-element/api/graphics-api.js
@@ -605,7 +605,7 @@ class GraphicsAPI extends BaseAPI {
/**
* Yield a snapshot of the current shape.
*/
- save() {
+ saveShape() {
return this.currentShape;
}
diff --git a/docs/news/2020-09-20.html b/docs/news/2020-09-18.html
similarity index 97%
rename from docs/news/2020-09-20.html
rename to docs/news/2020-09-18.html
index 160c0fd9..dbbf2c78 100644
--- a/docs/news/2020-09-20.html
+++ b/docs/news/2020-09-18.html
@@ -22,12 +22,12 @@
-
+
-
-
+
+
@@ -79,7 +79,7 @@
Rewriting the tech stack
-
Sun, 20 Sep 2020
+
Fri, 18 Sep 2020
diff --git a/docs/news/2020-09-20.md b/docs/news/2020-09-18.md
similarity index 100%
rename from docs/news/2020-09-20.md
rename to docs/news/2020-09-18.md
diff --git a/docs/news/2020-09-21-draft.md b/docs/news/2020-09-19-draft.md
similarity index 100%
rename from docs/news/2020-09-21-draft.md
rename to docs/news/2020-09-19-draft.md
diff --git a/docs/news/index.html b/docs/news/index.html
index 16651be1..9d91a720 100644
--- a/docs/news/index.html
+++ b/docs/news/index.html
@@ -94,7 +94,7 @@
diff --git a/docs/news/rss.xml b/docs/news/rss.xml
index 00c70690..caf64291 100644
--- a/docs/news/rss.xml
+++ b/docs/news/rss.xml
@@ -16,7 +16,7 @@
Rewriting the tech stack
- https://pomax.github.io/bezierinfo/news/2020-09-20.html
+ https://pomax.github.io/bezierinfo/news/2020-09-18.html
<p>Once upon a time, I needed to draw some Bezier curves because I was trying to create a Japanese kanji composition system that turned strokes into outlines, and that required knowing how to offset Bezier curves and... at the time (2011, time flies) there was no good single source of information for Bezier curves on the web. So I made one. Sure it started small, but it turns out that if you just keep adding bits to something, several years later you have quite the monster, and a single HTML file becomes intractible.</p>
<p>So, in 2016, when <a href="">React.js</a> exploded onto the scene, I rewrote the primer as a React app, and it became a lot easier to maintain. Like, <em>a lot</em> a lot. However, there was a downside: no JS meant no content. Sure, server-side rendering sort of existed, but not really, and because the Primer is hosted through github, there was no "server" to run. Plus, trying to rehydrate an app the size of the Primer from a giant HTML file had truly <em>dire</em> performance.</p>
@@ -44,8 +44,8 @@
<p>See you in the next post!</p>
<p>— Pomax</p>
- 2020-09-20
- 2020-09-20.html
+ 2020-09-18
+ 2020-09-18.html
diff --git a/docs/zh-CN/index.html b/docs/zh-CN/index.html
index 07653d75..a6598b6f 100644
--- a/docs/zh-CN/index.html
+++ b/docs/zh-CN/index.html
@@ -33,7 +33,7 @@
-
+
@@ -504,7 +504,7 @@
Scripts are disabled. Showing fallback image.
-
+
@@ -640,7 +640,7 @@ function Bezier(3,t):
Scripts are disabled. Showing fallback image.
-
+
@@ -649,7 +649,7 @@ function Bezier(3,t):
Scripts are disabled. Showing fallback image.
-
+
@@ -658,7 +658,7 @@ function Bezier(3,t):
Scripts are disabled. Showing fallback image.
-
+
@@ -753,7 +753,7 @@ function Bezier(3,t,w[]):
Scripts are disabled. Showing fallback image.
-
+
@@ -830,14 +830,14 @@ function RationalBezier(3,t,w[],r[]):
Scripts are disabled. Showing fallback image.
-
+ Scripts are disabled. Showing fallback image.
-
+
@@ -920,7 +920,7 @@ function RationalBezier(3,t,w[],r[]):
Scripts are disabled. Showing fallback image.
-
+
@@ -969,7 +969,7 @@ function RationalBezier(3,t,w[],r[]):
Scripts are disabled. Showing fallback image.
-
+
@@ -978,7 +978,7 @@ function RationalBezier(3,t,w[],r[]):
Scripts are disabled. Showing fallback image.
-
+
@@ -1022,7 +1022,7 @@ function RationalBezier(3,t,w[],r[]):
Scripts are disabled. Showing fallback image.
-
+