initial sketch
This commit is contained in:
parent
6363d7b2d9
commit
d71b18dbcc
|
@ -0,0 +1,155 @@
|
||||||
|
class Drawing {
|
||||||
|
constructor() {
|
||||||
|
const div = document.createElement('div');
|
||||||
|
const buttonsDiv = document.createElement('div');
|
||||||
|
this.startButton = document.createElement('button');
|
||||||
|
this.startButton.onclick = () => this.start();
|
||||||
|
this.startButton.innerHTML = "Start";
|
||||||
|
this.stopButton = document.createElement('button');
|
||||||
|
this.stopButton.onclick = () => this.stop();
|
||||||
|
this.stopButton.innerHTML = "Stop";
|
||||||
|
this.canvas = document.createElement('canvas');
|
||||||
|
this.canvas.width = 200;
|
||||||
|
this.canvas.height = 200;
|
||||||
|
buttonsDiv.appendChild(this.startButton);
|
||||||
|
buttonsDiv.appendChild(this.stopButton);
|
||||||
|
div.appendChild(buttonsDiv);
|
||||||
|
div.appendChild(this.canvas);
|
||||||
|
document.body.appendChild(div);
|
||||||
|
this.ctx = this.canvas.getContext('2d');
|
||||||
|
this.offset = {x: 0, y: 0};
|
||||||
|
this.sequence = [];
|
||||||
|
this.t = 0;
|
||||||
|
this.rt = 0;
|
||||||
|
this.dt = 0;
|
||||||
|
this.points = {};
|
||||||
|
this.stopped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel([x, y]) {
|
||||||
|
return [
|
||||||
|
this.offset.x + x,
|
||||||
|
this.canvas.height - this.offset.y - y
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
setOffset([x, y]) {
|
||||||
|
this.sequence.push(() => {
|
||||||
|
this.offset = {x, y};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setStroke(style, width) {
|
||||||
|
this.sequence.push(() => {
|
||||||
|
this.ctx.strokeStyle = style;
|
||||||
|
this.ctx.lineWidth = width;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setFill(style) {
|
||||||
|
this.sequence.push(() => {
|
||||||
|
this.ctx.fillStyle = style;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
line(p1, p2) {
|
||||||
|
this.sequence.push(() => {
|
||||||
|
this.ctx.beginPath();
|
||||||
|
this.ctx.moveTo(...this.pixel(this.getPoint(p1)));
|
||||||
|
this.ctx.lineTo(...this.pixel(this.getPoint(p2)));
|
||||||
|
this.ctx.stroke();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
polyline(...points) {
|
||||||
|
this.sequence.push(() => {
|
||||||
|
this.ctx.beginPath();
|
||||||
|
this.ctx.moveTo(...this.pixel(points[0]));
|
||||||
|
for (let i = 1; i < points.length; i++) {
|
||||||
|
this.ctx.lineTo(...this.pixel(points[i]));
|
||||||
|
}
|
||||||
|
this.ctx.stroke();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
oscillatingValue(x1, x2, period) {
|
||||||
|
return x1 + (x2 - x1) * Math.sin(2*Math.PI*this.t/period);
|
||||||
|
}
|
||||||
|
|
||||||
|
oscillatingPoint([x1, y1], [x2, y2], period) {
|
||||||
|
const x = this.oscillatingValue(x1, x2, period);
|
||||||
|
const y = this.oscillatingValue(y1, y2, period);
|
||||||
|
return [x, y];
|
||||||
|
}
|
||||||
|
|
||||||
|
square(p) {
|
||||||
|
this.sequence.push(() => {
|
||||||
|
const [x, y] = this.getPoint(p);
|
||||||
|
this.ctx.fillRect(...this.pixel([x - 5, y - 5]), 10, 10);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
circle(p) {
|
||||||
|
this.sequence.push(() => {
|
||||||
|
this.ctx.beginPath();
|
||||||
|
this.ctx.ellipse(...this.pixel(this.getPoint(p)), 5, 5, 0, 0, 2*Math.PI);
|
||||||
|
this.ctx.fill();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
definePoint(name, fn) {
|
||||||
|
this.points[name] = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPoint(p) {
|
||||||
|
if (typeof p === 'string') {
|
||||||
|
const fn = this.points[p];
|
||||||
|
if (!fn) {
|
||||||
|
const e = new Error;
|
||||||
|
e.message = `Point '${p}' is not defined`;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
return fn();
|
||||||
|
} else {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
for (let action of this.sequence) {
|
||||||
|
action();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
animate() {
|
||||||
|
this.ctx.reset();
|
||||||
|
this.render();
|
||||||
|
if (!this.stopped) {
|
||||||
|
requestAnimationFrame((prevt) => {
|
||||||
|
const rt = document.timeline.currentTime;
|
||||||
|
const elapsed = rt - prevt;
|
||||||
|
if (this.elideInterval) {
|
||||||
|
this.dt = 0;
|
||||||
|
this.elideInterval = false;
|
||||||
|
} else {
|
||||||
|
this.dt = rt - this.rt + elapsed;
|
||||||
|
}
|
||||||
|
this.t += this.dt;
|
||||||
|
this.rt = rt;
|
||||||
|
this.animate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
this.stopped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
if (this.stopped) {
|
||||||
|
this.elideInterval = true;
|
||||||
|
this.stopped = false;
|
||||||
|
}
|
||||||
|
this.animate();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
body {
|
||||||
|
margin: 50px;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
border: 1px red dashed;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Physics - Prototyping</title>
|
||||||
|
<link rel="stylesheet" href="./main.css">
|
||||||
|
<script src="./draw.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
const d = new Drawing();
|
||||||
|
console.log('drawing', d);
|
||||||
|
d.setOffset([50, 50]);
|
||||||
|
d.setStroke('black', 4);
|
||||||
|
d.polyline([0, 100], [0, 0], [100, 0]);
|
||||||
|
d.definePoint('p1', () => d.oscillatingPoint([75, 125], [125, 125], 5000));
|
||||||
|
d.setStroke('red', 2);
|
||||||
|
d.line([0, 0], 'p1');
|
||||||
|
d.setFill('blue');
|
||||||
|
d.definePoint('p2', () => {
|
||||||
|
const [x, y] = d.getPoint('p1');
|
||||||
|
return [x, y - 25];
|
||||||
|
});
|
||||||
|
d.square('p2');
|
||||||
|
d.setFill('cyan');
|
||||||
|
d.circle('p1');
|
||||||
|
d.start();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
Loading…
Reference in New Issue