Skip to content

Commit 80268a0

Browse files
Merge pull request #65 from Demonstrandum/devel
Transforms on primitives & new example.
2 parents 8c42187 + f344cae commit 80268a0

File tree

8 files changed

+210
-14
lines changed

8 files changed

+210
-14
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ A friendlier way interact with the canvas.
55
jsdelivr CDN (use this to import):
66
- Canvas
77
```
8-
https://cdn.jsdelivr.net/gh/Demonstrandum/BasicCanvas@v1.2.2/lib/BasicCanvas.js
8+
https://cdn.jsdelivr.net/gh/Demonstrandum/BasicCanvas@v1.2.3/lib/BasicCanvas.js
99
```
1010
- Shapes
1111
```
12-
https://cdn.jsdelivr.net/gh/Demonstrandum/BasicCanvas@v1.2.2/lib/BasicShapes.js
12+
https://cdn.jsdelivr.net/gh/Demonstrandum/BasicCanvas@v1.2.3/lib/BasicShapes.js
1313
```
1414
- DOM
1515
```
16-
https://cdn.jsdelivr.net/gh/Demonstrandum/BasicCanvas@v1.2.2/lib/BasicDOM.js
16+
https://cdn.jsdelivr.net/gh/Demonstrandum/BasicCanvas@v1.2.3/lib/BasicDOM.js
1717
```
1818
### Docs
1919

@@ -83,7 +83,7 @@ sketch.loop(frame => {
8383

8484
Drawing a simple sinusoidal progressive wave:
8585
```js
86-
import * as BC from 'https://cdn.jsdelivr.net/gh/Demonstrandum/BasicCanvas@v1.2.2/lib/BasicCanvas.js';
86+
import * as BC from 'https://cdn.jsdelivr.net/gh/Demonstrandum/BasicCanvas@v1.2.3/lib/BasicCanvas.js';
8787
// If running this locally, you need a server running for `import`s to work, (for now).
8888

8989
use(BC) // To avoid having to write `BC.` all the time.

example/AM_GM_inequality.js

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import * as BC from '../lib/BasicCanvas.js';
2+
import { ellipse, line, rectangle } from '../lib/BasicShapes.js';
3+
4+
use(BC);
5+
6+
// Load 'mathcal' font.
7+
load_font('Parisienne',
8+
"url(https://fonts.gstatic.com/s/parisienne/v8/E21i_d3kivvAkxhLEVZpQyhwDw.woff2)");
9+
10+
const a_mean_svg = new Image();
11+
a_mean_svg.src = './a_mean.svg';
12+
const g_mean_svg = new Image();
13+
g_mean_svg.src = './g_mean.svg';
14+
15+
const r = 260
16+
const G = (a, b) => Math.sqrt(a * b);
17+
18+
const BG = HEX('#fff');
19+
const COLOUR_A = HEX('#f47').to_rgb();
20+
const COLOUR_B = HEX('#3bf').to_rgb();
21+
22+
const sketch = canvas_id('sketch');
23+
window.sketch = sketch;
24+
sketch.dimensions(600, 400);
25+
sketch.translate(sketch.width / 2, 3 * sketch.height / 4);
26+
sketch.scale(1, -1);
27+
sketch.text_align = 'center'
28+
29+
const dip = -5;
30+
31+
let a = 400;
32+
let follow = false;
33+
mouse_down(() => {
34+
follow = true;
35+
}, sketch);
36+
mouse_up(() => {
37+
follow = false;
38+
}, sketch);
39+
40+
sketch.loop(() => {
41+
sketch.background(BG, true);
42+
43+
if (follow) {
44+
a = sketch.mouse.x + r;
45+
if (a > 2*r-40)
46+
a = 2*r-40;
47+
else if (a < 40)
48+
a = 40;
49+
a = Math.round(a) || 400;
50+
}
51+
const b = 2*r - a;
52+
const g = G(a, b);
53+
54+
sketch.fill = 'transparent'
55+
sketch.stroke = 'black'
56+
sketch.stroke_weight = 1;
57+
sketch.stroke_dash = [];
58+
sketch.render(ellipse(P(0, 0), r));
59+
sketch.render(line(P(-r - 20, 0), P(r + 20, 0)));
60+
61+
sketch.stroke_dash = [4, 5];
62+
sketch.render('A', line(P(0, dip), P(0, r)));
63+
sketch.render('G', line(P(a-r, dip), P(a-r, g)));
64+
sketch.stroke_dash = [8, 5];
65+
sketch.render('delta', line(P(0, g), P(a-r, g)));
66+
67+
sketch.stroke_weight = 0;
68+
sketch.fill = 'black';
69+
sketch.font = "32px 'Parisienne'";
70+
sketch.temp(() => {
71+
sketch.unscale();
72+
sketch.text('A', P(0, -r - 10));
73+
sketch.text('G', P(a-r, -g - 10));
74+
});
75+
76+
sketch.fill = 'transparent';
77+
sketch.stroke_dash = [7, 2];
78+
sketch.stroke_weight = 2;
79+
sketch.stroke = COLOUR_A;
80+
sketch.render('a', line(P(-r, dip), P(a-r, dip)));
81+
sketch.render(line(P(-r, 0), P(a-r, g)));
82+
sketch.stroke = COLOUR_B;
83+
sketch.render('b', line(P(a-r, dip), P(a+b-r, dip)));
84+
sketch.render(line(P(r, 0), P(a-r, g)));
85+
86+
sketch.stroke = 'gray';
87+
sketch.shape(rectangle(P(a-r, g), 20))
88+
.rotate(3*Math.PI/2 - Math.atan(a/g))
89+
.render();
90+
91+
sketch.stroke_weight = 0;
92+
sketch.font = "italic 24px 'CMUClassicalSerifItalic'";
93+
sketch.fill = COLOUR_A
94+
sketch.temp(() => {
95+
sketch.unscale();
96+
sketch.text('a', Point(a/2-r - 22, 30));
97+
sketch.font = "24px 'CMUSerifRoman'";
98+
sketch.text(' = ' + a, Point(a/2-r + 22, 30));
99+
});
100+
101+
sketch.fill.a = 100;
102+
sketch.render(shape => {
103+
shape.vertex(P(-r, 0));
104+
shape.vertex(P(a-r, g));
105+
shape.vertex(P(a-r, 0));
106+
shape.close()
107+
});
108+
sketch.fill.a = 255;
109+
110+
sketch.fill = COLOUR_B
111+
sketch.temp(() => {
112+
sketch.unscale();
113+
sketch.text('b', Point(a-r + b/2 - 22, 30));
114+
sketch.font = "24px 'CMUSerifRoman'";
115+
sketch.text(' = ' + b, Point(a-r + b/2 + 22, 30));
116+
});
117+
118+
sketch.fill.a = 100;
119+
sketch.render(shape => {
120+
shape.vertex(P(r, 0));
121+
shape.vertex(P(a-r, g));
122+
shape.vertex(P(a-r, 0));
123+
shape.close()
124+
});
125+
sketch.fill.a = 255;
126+
127+
128+
sketch.temp(() => {
129+
sketch.unscale();
130+
sketch.context.drawImage(a_mean_svg, -75, -r/2);
131+
sketch.context.drawImage(g_mean_svg, a-r + 5, -g/2);
132+
});
133+
});
134+
135+
136+
document.body.html`
137+
<div id="caption">
138+
<p style="font-family: 'CMUSerifRoman', sans-serif">
139+
Click and drag to interact with the proof.
140+
</p>
141+
<p>\[ \frac{a+b}{2} \ge \sqrt{ab} \]</p>
142+
</div>
143+
`;
144+
145+
css`#caption {
146+
position: absolute;
147+
top: 50%;
148+
left: 50%;
149+
transform: translate(-50%, -50%);
150+
padding-bottom: 40px;
151+
margin-top: ${3 * sketch.height / 4}px;
152+
}`;

example/a_mean.svg

Lines changed: 2 additions & 0 deletions
Loading

example/g_mean.svg

Lines changed: 2 additions & 0 deletions
Loading

example/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
<option value="orthographic.js">orthographic.js</option>
8282
<option value="weak_perspective.js">weak_perspective.js</option>
8383
<option value="vector_plot.js">vector_plot.js</option>
84+
<option value="AM_GM_inequality.js">AM_GM_inequality.js</option>
8485
<option value="wiggler.js">wiggler.js (Snake with physics)</option>
8586
<option value="sinusoidal.js">sinusoidal.js</option>
8687
<option value="joy.js">joy.js</option>

example/pendulum_graph.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ sketch.loop(() => {
9191
Point(0, sketch.corner.y),
9292
Point(0, sketch.corner.y + sketch.height)));
9393

94-
sketch.context.setLineDash([4, 5]);
94+
sketch.stroke_dash = [4, 5];
9595
sketch.fill = 'transparent';
9696
sketch.stroke = ANGLE_COLOUR;
9797
const cw = ϑ < 0;
@@ -103,7 +103,7 @@ sketch.loop(() => {
103103
sketch.stroke = Y_COLOUR;
104104
sketch.render('y-value', line(Point(coord.x, L/2), coord));
105105

106-
sketch.context.setLineDash([]);
106+
sketch.stroke_dash = [];
107107
sketch.stroke = 'transparent';
108108

109109
sketch.fill = X_COLOUR;

lib/BasicCanvas.js

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,22 @@ class PointObj {
322322
class RGBAObj {
323323
constructor(r, g, b, a) {
324324
[this.r, this.g, this.b, this.a] = [r, g, b, a].map(Math.round);
325-
this.rgba = [this.r, this.g, this.b, this.a];
326-
this.rgb = this.rgba.slice(0, -1);
325+
}
326+
327+
get rgba() {
328+
return [this.r, this.g, this.b, this.a];
329+
}
330+
331+
get rgb() {
332+
return this.rgba.slice(0, -1);
333+
}
334+
335+
set rgba(arr) {
336+
[this.r, this.g, this.b, this.a] = arr;
337+
}
338+
339+
set rgb(arr) {
340+
[this.r, this.g, this.b] = arr;
327341
}
328342

329343
toString() {
@@ -457,8 +471,10 @@ class HEXobj {
457471
given = hex.split('#').slice(-1)[0];
458472
} else if (type(hex) === 'array') {
459473
given = plain(...hex).split('#').slice(-1)[0];
460-
} else {
474+
} else if (type(hex) === 'number') {
461475
given = hex.toString(16).padStart(6, '0');
476+
} else {
477+
given = hex.toString().split('#').slice(-1)[0];
462478
}
463479

464480
if (given.length === 3 || given.length === 4) {
@@ -490,7 +506,10 @@ class HEXobj {
490506
const str = chars.join('');
491507
this.str = '#' + str;
492508
this.hex = parseInt(str, 16);
493-
this.rgb = this.to_rgb();
509+
}
510+
511+
get rgb() {
512+
return this.to_rgb();
494513
}
495514

496515
to_rgb() {
@@ -712,7 +731,7 @@ export const to_rgb = c => {
712731
// Check rgb
713732
match = (
714733
c.match(rgb_regex) ||
715-
c.match(rgba_regex)
734+
c.match(rgba_regex)
716735
);
717736
if (match) {
718737
if (match[4]) {
@@ -771,7 +790,8 @@ class Shape {
771790
style(fill = this.canvas.fill,
772791
stroke = this.canvas.stroke,
773792
stroke_weight = this.canvas.stroke_weight,
774-
stroke_cap = this.canvas.stroke_cap) {
793+
stroke_cap = this.canvas.stroke_cap,
794+
stroke_dash = this.canvas.stroke_dash) {
775795
if (stroke_weight === 0) {
776796
stroke = TRANSPARENT;
777797
}
@@ -780,6 +800,7 @@ class Shape {
780800
c.strokeStyle = stroke.toString();
781801
c.lineWidth = stroke_weight;
782802
c.lineCap = stroke_cap;
803+
c.setLineDash(stroke_dash);
783804
return this;
784805
}
785806

@@ -896,9 +917,17 @@ class Shape {
896917
}
897918
}
898919
} else {
920+
const c = this.canvas.context;
921+
c.save()
922+
c.translate(this.center.x + this.translation[0],
923+
this.center.y + this.translation[1]);
924+
c.scale(this.scaling[0], this.scaling[1]);
925+
c.rotate(this.rotation);
926+
c.translate(-this.center.x, -this.center.y);
899927
this.primitive();
900928
this.style(temp_color);
901929
this.flesh();
930+
c.restore();
902931
return this;
903932
}
904933

@@ -983,6 +1012,7 @@ class Canvas {
9831012
// Main API properties.
9841013
this.fill = RGBA(255, 255, 255, 0);
9851014
this.stroke = RGB(0, 0, 0);
1015+
this._stroke_dash = [];
9861016
this._stroke_weight = 1;
9871017
this.stroke_cap = 'butt';
9881018
this.font = '16px sans-serif';
@@ -1029,12 +1059,21 @@ class Canvas {
10291059
this.update_context();
10301060
}
10311061

1062+
get stroke_dash() {
1063+
return this._stroke_dash;
1064+
}
1065+
1066+
set stroke_dash(d) {
1067+
this.context.setLineDash(d);
1068+
this._stroke_dash = d;
1069+
}
1070+
10321071
get stroke_weight() {
10331072
return this._stroke_weight / Math.max(...(this.stretch).map(e => Math.abs(e)));
10341073
}
10351074

10361075
set stroke_weight(w) {
1037-
this.context.lineWidth =w;
1076+
this.context.lineWidth = w;
10381077
this._stroke_weight = w;
10391078
}
10401079

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"name": "basiccanvas",
44
"title": "BasicCanvas",
55
"description": "Simple JavaScript canvas abstractions.",
6-
"version": "1.2.2",
6+
"version": "1.2.3",
77
"main": "lib/BasicCanvas.js",
88
"homepage": "https://github.com/Demonstrandum/BasicCanvas/",
99
"author": {

0 commit comments

Comments
 (0)