markdown drawings!

This commit is contained in:
Ladd Hoffman 2024-06-22 15:01:10 -05:00
parent 83778bb129
commit dfbe9e34ed
5 changed files with 153 additions and 46 deletions

63
draw.js
View File

@ -23,6 +23,7 @@ class Drawing {
this.rt = 0; this.rt = 0;
this.dt = 0; this.dt = 0;
this.points = {}; this.points = {};
this.values = {};
this.stopped = true; this.stopped = true;
this.frame = [[-10, -10], [110, 110]]; this.frame = [[-10, -10], [110, 110]];
this.frameMargin = 10; this.frameMargin = 10;
@ -181,6 +182,20 @@ class Drawing {
} }
} }
defineValue(name, fn) {
this.values[name] = fn;
}
getValue(name) {
const fn = this.values[name];
if (!fn) {
const e = new Error;
e.message = `Value '${name}' is not defined`;
throw e;
}
return fn();
}
line(p1, p2) { line(p1, p2) {
this.sequence.push(() => { this.sequence.push(() => {
this.ctx.beginPath(); this.ctx.beginPath();
@ -280,7 +295,6 @@ class Drawing {
} }
func(opts, fn) { func(opts, fn) {
const origin = opts?.origin ?? [0, 0];
const domain = opts?.domain ?? [this.frame[0][0], this.frame[1][0]]; const domain = opts?.domain ?? [this.frame[0][0], this.frame[1][0]];
const step = opts?.step ?? 1; const step = opts?.step ?? 1;
this.sequence.push(() => { this.sequence.push(() => {
@ -306,6 +320,9 @@ class Drawing {
const [cmd, ...args] = line.split(' '); const [cmd, ...args] = line.split(' ');
// console.log({cmd, args}); // console.log({cmd, args});
switch (cmd) { switch (cmd) {
case 'start': {
d.start();
} break;
case 'title': { case 'title': {
d.setTitle(args.join(' ')); d.setTitle(args.join(' '));
} break; } break;
@ -315,8 +332,12 @@ class Drawing {
case 'buttons': { case 'buttons': {
d.addButtons(); d.addButtons();
} break; } break;
case 'scale': {
const [scale] = args;
d.setScale(scale);
} break;
case 'frame': { case 'frame': {
const [x1, y1, x2, y2] = args.map(x => parseInt(x)); const [x1, y1, x2, y2] = args.map(x => eval(x));
d.setFrame([x1, y1], [x2, y2]); d.setFrame([x1, y1], [x2, y2]);
} break; } break;
case 'axes': { case 'axes': {
@ -335,7 +356,7 @@ class Drawing {
case 'point': { case 'point': {
const [name, ...rest] = args; const [name, ...rest] = args;
let body = rest.join(' '); let body = rest.join(' ');
while (lines[i + 1].startsWith(' ')) { while (i < lines.length - 1 && lines[i + 1].startsWith(' ')) {
body += lines[i + 1]; body += lines[i + 1];
i += 1; i += 1;
} }
@ -345,14 +366,46 @@ class Drawing {
})(d); })(d);
}); });
} break; } break;
case 'value': {
const [name, ...rest] = args;
let body = rest.join(' ');
while (i < lines.length - 1 && lines[i + 1].startsWith(' ')) {
body += lines[i + 1];
i += 1;
}
d.defineValue(name, () => {
return (function(_) {
return eval(body);
})(d);
});
} break;
case 'circle': case 'circle':
case 'square': { case 'square': {
const p = args[0]; const p = args[0];
const traceAge = args[1] ? parseInt(args[1]) : 0; const traceAge = args[1] ? parseInt(args[1]) : 0;
d[cmd](p, {trace: {age: traceAge}}); d[cmd](p, {trace: {age: traceAge}});
} break; } break;
case 'start': { case 'func': {
d.start(); let body = args.join(' ');
while (i < lines.length - 1 && lines[i + 1].startsWith(' ')) {
body += lines[i + 1];
i += 1;
}
d.func({step: 0.1}, (x) => {
return (function(_) {
return eval(body);
})(d);
});
} break;
case 'eval': {
let body = args.join(' ');
while (i < lines.length - 1 && lines[i + 1].startsWith(' ')) {
body += lines[i + 1];
i += 1;
}
(function(_) {
eval(body);
})(d);
} break; } break;
} }
} }

3
reveal-override.css Normal file
View File

@ -0,0 +1,3 @@
body {
--r-heading-text-transform: none;
}

View File

@ -11,6 +11,7 @@
<link rel="stylesheet" href="./node_modules/reveal.js/dist/reset.css"> <link rel="stylesheet" href="./node_modules/reveal.js/dist/reset.css">
<link rel="stylesheet" href="./node_modules/reveal.js/dist/reveal.css"> <link rel="stylesheet" href="./node_modules/reveal.js/dist/reveal.css">
<link rel="stylesheet" href="./node_modules/reveal.js/dist/theme/white.css"> <link rel="stylesheet" href="./node_modules/reveal.js/dist/theme/white.css">
<link rel="stylesheet" href="./reveal-override.css">
<!-- Theme used for syntax highlighted code --> <!-- Theme used for syntax highlighted code -->
<link rel="stylesheet" href="./node_modules/reveal.js/plugin/highlight/monokai.css"> <link rel="stylesheet" href="./node_modules/reveal.js/plugin/highlight/monokai.css">
@ -19,40 +20,6 @@
<script src="./draw.js"></script> <script src="./draw.js"></script>
<div class="reveal"> <div class="reveal">
<div class="slides"> <div class="slides">
<section>
<h2>Slide 1</h2>
<p>Content... `a = b / c`</p>
<div id="d3"></div>
<script>
{
const d = new Drawing('d3');
d.setTitle('Test Drawing');
d.line([0, 0], [100, 100]);
d.render();
}
</script>
</section>
<section data-markdown>
<textarea data-template>
## Slide 2
- Item 1
- Item 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6
<div id="d1"></div>
<script>
{
const d = new Drawing('d1');
d.setTitle('Test Drawing');
d.line([0, 0], [100, 100]);
d.render();
}
</script>
</textarea>
</section>
<section data-markdown="test.md"></section> <section data-markdown="test.md"></section>
</div> </div>
</div> </div>

View File

@ -109,7 +109,7 @@
d.setStroke('green', 1); d.setStroke('green', 1);
d.line([0, 0], [v0x, v0y]); d.line([0, 0], [v0x, v0y]);
d.setFill('blue'); d.setFill('blue');
const projectile = d.circle('p1', {trace: {age: -1}}) const projectile = d.circle('p1', {trace: {age: -1}});
d.onStart(() => { d.onStart(() => {
if (d.t == 0) { if (d.t == 0) {
projectile.reset(); projectile.reset();

94
test.md
View File

@ -1,12 +1,9 @@
## Slide 3 ## Slide 1
Testing
<div id="d2"></div>
```drawing ```drawing
title Test Drawing! title Test Drawing!
caption This is a test caption This is a test
scale 2.0
buttons buttons
frame 0 0 200 100 frame 0 0 200 100
axes 200 100 axes 200 100
@ -22,3 +19,90 @@ fill green
circle p3 1000 circle p3 1000
start start
``` ```
---
## Slide 2
```drawing
title Sine Wave
caption `y = sin(x)`
scale 64
frame 0 -1 2*Math.PI 1
stroke black 4
eval _.line([0, -1], [0, 1])
eval _.line([0, 0], [2*Math.PI, 0])
stroke red 2
func Math.sin(x)
```
---
## Slide 3
```drawing
title Oscillating Sine Wave
caption `y = sin(x) * sin(t)`
scale 64
frame 0 -1 2*Math.PI 1
stroke black 4
eval _.line([0, -1], [0, 1])
eval _.line([0, 0], [2*Math.PI, 0])
stroke red 2
func Math.sin(x) * _.oscillatingValue(-1, 1, 500)
start
```
---
## Slide 4
```drawing
title Travelling Sine Wave
caption `y = sin(x + t)`
scale 64
frame 0 -1 2*Math.PI 1
stroke black 4
eval _.line([0, -1], [0, 1])
eval _.line([0, 0], [2*Math.PI, 0])
stroke red 2
func Math.sin(x + 2*Math.PI*_.t / 1000)
start
```
---
## Slide 5
```drawing
title Projectile
caption `y = v_(0y) * t - g * t^2`<br>`x = v_(0x) * t`
scale 2
frame 0 0 300 100
stroke black 4
eval _.polyline([0, 100], [0, 0], [300, 0]);
value v0 75
value angle Math.PI / 4
value v0x _.getValue('v0') * Math.cos(_.getValue('angle'))
value v0y _.getValue('v0') * Math.sin(_.getValue('angle'))
point p1 (function() {
const t = _.t / 1000;
const x = _.getValue('v0x') * t;
const y = _.getValue('v0y') * t - 9.81 * t**2;
if (t > 0 && (y <= 0 || x >= _.frame[1][0])) {
_.stop();
_.t = 0;
}
return [x, y];
})()
stroke green 1
eval _.line([0, 0], [_.getValue('v0x'), _.getValue('v0y')])
fill blue
eval const projectile = d.circle('p1', {trace: {age: -1}});
d.onStart(() => {
if (d.t == 0) {
projectile.reset();
}
})
start
```