Skip to content

Commit 2228130

Browse files
committed
08: refacter code by using MVVM pattern, but really slow
Signed-off-by: Soshi Katsuta <soshi.katsuta@gmail.com>
1 parent 427475f commit 2228130

1 file changed

Lines changed: 78 additions & 29 deletions

File tree

Lines changed: 78 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,90 @@
1-
class Painter {
2-
constructor(ctx) {
3-
ctx.strokeStyle = '#BADA55';
4-
ctx.lineJoin = 'round';
5-
ctx.lineCap = 'round';
6-
this.ctx = ctx;
1+
class Notifier {
2+
constructor() {
3+
this.handlers = [];
4+
}
75

8-
this.MIN_LINE_WIDTH = 1;
9-
this.MAX_LINE_WIDTH = 100;
6+
observe(handler) {
7+
this.handlers.push(handler);
8+
}
109

11-
this.isDrawing = false;
12-
this.lastX = this.lastY = 0;
13-
this.hue = 0;
14-
this.direction = true;
10+
fire() {
11+
this.handlers.forEach(handler => handler());
1512
}
13+
}
1614

17-
draw(e) {
18-
if (!this.isDrawing) { return; }
15+
class Painting {
16+
constructor(lineWidth) {
17+
this.lineWidth = lineWidth;
18+
this.lastX = this.lastY = this.hue = 0;
19+
this.direction = true;
20+
this.notifier = new Notifier();
21+
}
1922

20-
const ctx = this.ctx;
21-
ctx.strokeStyle = `hsl(${this.hue}, 100%, 50%)`;
22-
ctx.beginPath();
23-
ctx.moveTo(this.lastX, this.lastY);
24-
ctx.lineTo(e.offsetX, e.offsetY);
25-
ctx.stroke();
23+
observe(handler) {
24+
this.notifier.observe(handler);
25+
}
2626

27-
[this.lastX, this.lastY] = [e.offsetX, e.offsetY];
27+
draw(e) {
28+
this.lastX = e.offsetX;
29+
this.lastY = e.offsetY;
2830
this.hue < 360 ? this.hue++ : this.hue = 0;
2931

30-
if (ctx.lineWidth <= this.MIN_LINE_WIDTH || ctx.lineWidth >= this.MAX_LINE_WIDTH) {
32+
const minLineWidth = 1;
33+
const maxLineWidth = 100;
34+
if (this.lineWidth < minLineWidth || this.lineWidth > maxLineWidth) {
3135
this.direction = !this.direction;
3236
}
33-
this.direction ? ctx.lineWidth++ : ctx.lineWidth--;
37+
this.direction ? this.lineWidth++ : this.lineWidth--;
38+
39+
this.notifier.fire();
40+
}
41+
42+
startDrawing(e) {
43+
this.lastX = e.offsetX;
44+
this.lastY = e.offsetY;
45+
46+
this.notifier.fire();
47+
}
48+
}
49+
50+
class CtxViewModel {
51+
constructor(ctx) {
52+
this.painting = new Painting(ctx.lineWidth);
53+
54+
this.isDrawing = false;
55+
this.lastX = this.painting.lastX;
56+
this.lastY = this.painting.lastY;
57+
this.hue = this.painting.hue;
58+
59+
this.ctx = ctx;
60+
this.ctx.lineWidth = 1;
61+
this.ctx.lineJoin = 'round';
62+
this.ctx.lineCap = 'round';
63+
this.ctx.strokeStyle = '#BADA55';
64+
65+
// register handler to observer
66+
this.painting.observe(() => {
67+
this.lastX = this.painting.lastX;
68+
this.lastY = this.painting.lastY;
69+
this.ctx.lineWidth = this.painting.lineWidth;
70+
this.ctx.strokeStyle = `hsl(${this.painting.hue}, 100%, 50%)`;
71+
});
72+
}
73+
74+
draw(e) {
75+
if (!this.isDrawing) { return; }
76+
77+
this.painting.draw(e);
78+
79+
this.ctx.beginPath();
80+
this.ctx.moveTo(this.lastX, this.lastY);
81+
this.ctx.lineTo(e.offsetX, e.offsetY);
82+
this.ctx.stroke();
3483
}
3584

3685
startDrawing(e) {
3786
this.isDrawing = true;
38-
[this.lastX, this.lastY] = [e.offsetX, e.offsetY];
87+
this.painting.startDrawing(e);
3988
}
4089

4190
stopDrawing() {
@@ -46,10 +95,10 @@ class Painter {
4695
const canvas = document.querySelector('#draw');
4796
canvas.width = window.innerWidth;
4897
canvas.height = window.innerHeight;
49-
const painter = new Painter(canvas.getContext('2d'));
98+
const ctxVm = new CtxViewModel(canvas.getContext('2d'));
5099
[
51-
{ eventType: 'mousemove', callback: e => painter.draw(e) },
52-
{ eventType: 'mousedown', callback: e => painter.startDrawing(e) },
53-
{ eventType: 'mouseup', callback: () => painter.stopDrawing() },
54-
{ eventType: 'mouseout', callback: () => painter.stopDrawing() }
100+
{ eventType: 'mousemove', callback: e => ctxVm.draw(e) },
101+
{ eventType: 'mousedown', callback: e => ctxVm.startDrawing(e) },
102+
{ eventType: 'mouseup', callback: () => ctxVm.stopDrawing() },
103+
{ eventType: 'mouseout', callback: () => ctxVm.stopDrawing() }
55104
].forEach(({eventType, callback}) => canvas.addEventListener(eventType, callback));

0 commit comments

Comments
 (0)