@@ -16,7 +16,11 @@ var color_choices = [
16
16
var radiansPer45Degrees = Math . PI / 4 ;
17
17
18
18
var canvas = document . getElementById ( 'canvas' ) ;
19
- var ctx = canvas . getContext ( '2d' ) ;
19
+ var mainCtx = canvas . getContext ( '2d' ) ;
20
+ var offScreenCanvas = document . createElement ( 'canvas' ) ;
21
+ var offScreenCtx = offScreenCanvas . getContext ( '2d' ) ;
22
+ offScreenCanvas . width = canvas . width ;
23
+ offScreenCanvas . height = canvas . height ;
20
24
21
25
var img = new Image ( ) ;
22
26
var rgb_color = "#FF00FF" ;
@@ -38,14 +42,19 @@ var showNormalized = false;
38
42
var modeMessage = document . querySelector ( '#mode' ) ;
39
43
// var coords = document.querySelector('#coords');
40
44
45
+ function blitCachedCanvas ( ) {
46
+ mainCtx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
47
+ mainCtx . drawImage ( offScreenCanvas , 0 , 0 ) ;
48
+ }
49
+
41
50
function clipboard ( selector ) {
42
51
var copyText = document . querySelector ( selector ) . innerText ;
43
52
navigator . clipboard . writeText ( copyText ) ;
44
53
}
45
54
46
55
function clearDrawings ( ) {
47
- ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
48
- ctx . drawImage ( img , 0 , 0 ) ;
56
+ offScreenCtx . clearRect ( 0 , 0 , offScreenCanvas . width , offScreenCanvas . height ) ;
57
+ blitCachedCanvas ( ) ;
49
58
}
50
59
51
60
function isClockwise ( vertices ) {
@@ -80,9 +89,8 @@ function onPathClose() {
80
89
masterPoints . push ( points ) ;
81
90
points = [ ] ;
82
91
masterColors . push ( rgb_color ) ;
83
- clearDrawings ( ) ;
84
- drawAllPolygons ( ) ;
85
-
92
+ drawAllPolygons ( offScreenCtx ) ;
93
+ blitCachedCanvas ( ) ;
86
94
rgb_color = color_choices [ ( masterColors . length ) % ( color_choices . length ) ] ;
87
95
}
88
96
@@ -94,15 +102,18 @@ img.onload = function() {
94
102
canvas . style . height = img . height * scaleFactor + 'px' ;
95
103
canvas . width = img . width ;
96
104
canvas . height = img . height ;
97
- ctx . drawImage ( img , 0 , 0 ) ;
105
+ offScreenCanvas . width = img . width ;
106
+ offScreenCanvas . height = img . height ;
107
+ offScreenCtx . drawImage ( img , 0 , 0 ) ;
108
+ blitCachedCanvas ( ) ;
98
109
} ;
99
110
100
- function makeLine ( x1 , y1 , x2 , y2 ) {
111
+ function makeLine ( ctx , x1 , y1 , x2 , y2 ) {
101
112
ctx . moveTo ( x1 , y1 ) ;
102
113
ctx . lineTo ( x2 , y2 ) ;
103
114
}
104
115
105
- function drawNode ( x , y , stroke = null ) {
116
+ function drawNode ( ctx , x , y , stroke = null ) {
106
117
if ( stroke ) {
107
118
ctx . strokeStyle = stroke ;
108
119
}
@@ -121,20 +132,22 @@ function getScaledCoords(e) {
121
132
return [ x / scaleFactor , y / scaleFactor ] ;
122
133
}
123
134
124
- function drawAllPolygons ( ) {
135
+ function drawAllPolygons ( ctx ) {
136
+ ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
137
+ ctx . drawImage ( img , 0 , 0 ) ;
125
138
// draw polygons as subpaths and fill all at once
126
139
// we do this to avoid overlapping polygons becoming opaque
127
140
ctx . beginPath ( ) ;
128
141
ctx . fillStyle = fill_color ;
129
142
for ( var i = 0 ; i < masterPoints . length ; i ++ ) {
130
143
var newpoints = masterPoints [ i ] ;
131
144
for ( var j = 1 ; j < newpoints . length ; j ++ ) {
132
- makeLine ( newpoints [ j - 1 ] [ 0 ] , newpoints [ j - 1 ] [ 1 ] , newpoints [ j ] [ 0 ] , newpoints [ j ] [ 1 ] ) ;
145
+ makeLine ( ctx , newpoints [ j - 1 ] [ 0 ] , newpoints [ j - 1 ] [ 1 ] , newpoints [ j ] [ 0 ] , newpoints [ j ] [ 1 ] ) ;
133
146
ctx . moveTo ( newpoints [ 0 ] [ 0 ] , newpoints [ 0 ] [ 1 ] ) ;
134
147
for ( var j = 1 ; j < newpoints . length ; j ++ ) {
135
148
ctx . lineTo ( newpoints [ j ] [ 0 ] , newpoints [ j ] [ 1 ] ) ;
136
149
}
137
- makeLine ( newpoints [ newpoints . length - 1 ] [ 0 ] , newpoints [ newpoints . length - 1 ] [ 1 ] , newpoints [ 0 ] [ 0 ] , newpoints [ 0 ] [ 1 ] ) ;
150
+ makeLine ( ctx , newpoints [ newpoints . length - 1 ] [ 0 ] , newpoints [ newpoints . length - 1 ] [ 1 ] , newpoints [ 0 ] [ 0 ] , newpoints [ 0 ] [ 1 ] ) ;
138
151
}
139
152
}
140
153
ctx . fill ( ) ;
@@ -147,7 +160,7 @@ function drawAllPolygons () {
147
160
148
161
ctx . beginPath ( ) ;
149
162
for ( var j = 1 ; j < newpoints . length ; j ++ ) {
150
- makeLine ( newpoints [ j - 1 ] [ 0 ] , newpoints [ j - 1 ] [ 1 ] , newpoints [ j ] [ 0 ] , newpoints [ j ] [ 1 ] ) ;
163
+ makeLine ( ctx , newpoints [ j - 1 ] [ 0 ] , newpoints [ j - 1 ] [ 1 ] , newpoints [ j ] [ 0 ] , newpoints [ j ] [ 1 ] ) ;
151
164
ctx . moveTo ( newpoints [ 0 ] [ 0 ] , newpoints [ 0 ] [ 1 ] ) ;
152
165
for ( var j = 1 ; j < newpoints . length ; j ++ ) {
153
166
ctx . lineTo ( newpoints [ j ] [ 0 ] , newpoints [ j ] [ 1 ] ) ;
@@ -158,12 +171,12 @@ function drawAllPolygons () {
158
171
159
172
// draw arc around each point
160
173
for ( var j = 0 ; j < newpoints . length ; j ++ ) {
161
- drawNode ( newpoints [ j ] [ 0 ] , newpoints [ j ] [ 1 ] ) ;
174
+ drawNode ( ctx , newpoints [ j ] [ 0 ] , newpoints [ j ] [ 1 ] ) ;
162
175
}
163
176
}
164
177
}
165
178
166
- function getParentPoints ( ) {
179
+ function getParentPoints ( ) {
167
180
var parentPoints = [ ] ;
168
181
for ( var i = 0 ; i < masterPoints . length ; i ++ ) {
169
182
parentPoints . push ( masterPoints [ i ] ) ;
@@ -240,31 +253,35 @@ canvas.addEventListener('mousemove', function(e) {
240
253
xcoord . innerHTML = x ;
241
254
ycoord . innerHTML = y ;
242
255
256
+ var ctx = mainCtx ;
257
+ ctx . lineWidth = 5 ;
258
+ ctx . lineJoin = 'bevel' ;
259
+ ctx . fillStyle = 'white' ;
260
+
243
261
if ( canvas . style . cursor == 'crosshair' ) {
244
- clearDrawings ( ) ;
245
- drawAllPolygons ( ) ;
262
+ blitCachedCanvas ( ) ;
246
263
247
264
for ( var i = 0 ; i < points . length - 1 ; i ++ ) {
248
265
ctx . strokeStyle = rgb_color ;
249
266
ctx . beginPath ( ) ;
250
267
ctx . lineJoin = 'bevel' ;
251
- makeLine ( points [ i ] [ 0 ] , points [ i ] [ 1 ] , points [ i + 1 ] [ 0 ] , points [ i + 1 ] [ 1 ] ) ;
268
+ makeLine ( ctx , points [ i ] [ 0 ] , points [ i ] [ 1 ] , points [ i + 1 ] [ 0 ] , points [ i + 1 ] [ 1 ] ) ;
252
269
ctx . closePath ( ) ;
253
270
ctx . stroke ( ) ;
254
271
255
- drawNode ( points [ i ] [ 0 ] , points [ i ] [ 1 ] ) ;
272
+ drawNode ( ctx , points [ i ] [ 0 ] , points [ i ] [ 1 ] ) ;
256
273
}
257
274
258
275
259
276
if ( ( points . length > 0 && drawMode == "polygon" ) || ( points . length > 0 && points . length < 2 && drawMode == "line" ) ) {
260
277
ctx . beginPath ( ) ;
261
278
ctx . lineJoin = 'bevel' ;
262
279
ctx . strokeStyle = rgb_color ;
263
- makeLine ( points [ points . length - 1 ] [ 0 ] , points [ points . length - 1 ] [ 1 ] , x , y ) ;
280
+ makeLine ( ctx , points [ points . length - 1 ] [ 0 ] , points [ points . length - 1 ] [ 1 ] , x , y ) ;
264
281
ctx . closePath ( ) ;
265
282
ctx . stroke ( ) ;
266
283
267
- drawNode ( points [ i ] [ 0 ] , points [ i ] [ 1 ] ) ;
284
+ drawNode ( ctx , points [ i ] [ 0 ] , points [ i ] [ 1 ] ) ;
268
285
}
269
286
}
270
287
} ) ;
@@ -297,8 +314,11 @@ canvas.addEventListener('drop', function(e) {
297
314
canvas . style . height = img . height * scaleFactor + 'px' ;
298
315
canvas . width = img . width ;
299
316
canvas . height = img . height ;
317
+ offScreenCanvas . width = img . width ;
318
+ offScreenCanvas . height = img . height ;
300
319
canvas . style . borderRadius = '10px' ;
301
- ctx . drawImage ( img , 0 , 0 ) ;
320
+ offScreenCtx . drawImage ( img , 0 , 0 ) ;
321
+ blitCachedCanvas ( ) ;
302
322
} ;
303
323
// show coords
304
324
// document.getElementById('coords').style.display = 'inline-block';
@@ -382,7 +402,7 @@ canvas.addEventListener('click', function(e) {
382
402
383
403
points . push ( [ x , y ] ) ;
384
404
385
- drawNode ( x , y , rgb_color ) ;
405
+ drawNode ( mainCtx , x , y , rgb_color ) ;
386
406
387
407
if ( drawMode == "line" && points . length == 2 ) {
388
408
onPathClose ( ) ;
@@ -432,8 +452,7 @@ document.addEventListener('keydown', function(e) {
432
452
}
433
453
} )
434
454
435
- function update ( ) {
436
- drawAllPolygons ( ) ;
455
+ function rewritePoints ( ) {
437
456
var parentPoints = getParentPoints ( ) ;
438
457
writePoints ( parentPoints ) ;
439
458
}
@@ -443,26 +462,32 @@ function highlightButtonInteraction (buttonId) {
443
462
setTimeout ( ( ) => document . querySelector ( buttonId ) . classList . remove ( 'active' ) , 100 ) ;
444
463
}
445
464
446
- function undo ( ) {
465
+ function undo ( ) {
447
466
highlightButtonInteraction ( '#undo' ) ;
448
467
449
468
if ( points . length > 0 ) {
450
469
points . pop ( ) ;
451
- clearDrawings ( ) ;
452
- update ( ) ;
470
+ blitCachedCanvas ( ) ;
471
+ rewritePoints ( ) ;
453
472
454
473
if ( points . length === 0 ) {
455
474
return ;
456
475
}
457
476
477
+ var ctx = mainCtx ;
458
478
ctx . strokeStyle = rgb_color ;
459
- var i = 0 ;
460
- for ( ; i < points . length - 1 ; i ++ ) {
461
- makeLine ( points [ i ] [ 0 ] , points [ i ] [ 1 ] , points [ i + 1 ] [ 0 ] , points [ i + 1 ] [ 1 ] ) ;
462
- ctx . stroke ( ) ;
463
- drawNode ( points [ i ] [ 0 ] , points [ i ] [ 1 ] ) ;
479
+ ctx . fillStyle = 'white' ;
480
+ if ( points . length === 1 ) {
481
+ drawNode ( ctx , points [ 0 ] [ 0 ] , points [ 0 ] [ 1 ] ) ;
482
+ }
483
+ else {
484
+ drawNode ( ctx , points [ 0 ] [ 0 ] , points [ 0 ] [ 1 ] ) ;
485
+ for ( var i = 0 ; i < points . length - 1 ; i ++ ) {
486
+ makeLine ( ctx , points [ i ] [ 0 ] , points [ i ] [ 1 ] , points [ i + 1 ] [ 0 ] , points [ i + 1 ] [ 1 ] ) ;
487
+ ctx . stroke ( ) ;
488
+ drawNode ( ctx , points [ i + 1 ] [ 0 ] , points [ i + 1 ] [ 1 ] ) ;
489
+ }
464
490
}
465
- drawNode ( points [ i ] [ 0 ] , points [ i ] [ 1 ] ) ;
466
491
}
467
492
}
468
493
@@ -473,8 +498,8 @@ document.querySelector('#undo').addEventListener('click', function(e) {
473
498
function discardCurrentPolygon ( ) {
474
499
highlightButtonInteraction ( '#discard-current' ) ;
475
500
points = [ ] ;
476
- clearDrawings ( ) ;
477
- update ( ) ;
501
+ blitCachedCanvas ( ) ;
502
+ rewritePoints ( ) ;
478
503
}
479
504
480
505
document . querySelector ( '#discard-current' ) . addEventListener ( 'click' , function ( e ) {
@@ -483,7 +508,10 @@ document.querySelector('#discard-current').addEventListener('click', function(e)
483
508
484
509
function clearAll ( ) {
485
510
highlightButtonInteraction ( '#clear' )
486
- clearDrawings ( ) ;
511
+ mainCtx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
512
+ offScreenCtx . clearRect ( 0 , 0 , offScreenCanvas . width , offScreenCanvas . height ) ;
513
+ mainCtx . drawImage ( img , 0 , 0 ) ;
514
+ offScreenCtx . drawImage ( img , 0 , 0 ) ;
487
515
points = [ ] ;
488
516
masterPoints = [ ] ;
489
517
masterColors = [ ] ;
0 commit comments