@@ -12,8 +12,12 @@ var color_choices = [
12
12
"#CCCCCC" ,
13
13
] ;
14
14
15
+ var radiansPer45Degrees = Math . PI / 4 ;
16
+
15
17
var canvas = document . getElementById ( 'canvas' ) ;
16
18
var ctx = canvas . getContext ( '2d' ) ;
19
+ ctx . lineJoin = 'bevel' ;
20
+
17
21
var img = new Image ( ) ;
18
22
var rgb_color = color_choices [ Math . floor ( Math . random ( ) * color_choices . length ) ]
19
23
var opaque_color = 'rgba(0,0,0,0.5)' ;
@@ -28,13 +32,12 @@ var masterColors = [];
28
32
29
33
var drawMode
30
34
setDrawMode ( 'polygon' )
31
-
35
+ var constrainAngles = false ;
32
36
var showNormalized = false ;
33
37
34
38
var modeMessage = document . querySelector ( '#mode' ) ;
35
39
var coords = document . querySelector ( '#coords' ) ;
36
40
37
-
38
41
function clipboard ( selector ) {
39
42
var copyText = document . querySelector ( selector ) . innerText ;
40
43
navigator . clipboard . writeText ( copyText ) ;
@@ -53,6 +56,28 @@ function zoom(clicks) {
53
56
canvas . style . height = h + 'px' ;
54
57
}
55
58
59
+ function closePath ( ) {
60
+ canvas . style . cursor = 'default' ;
61
+ masterPoints . push ( points ) ;
62
+ masterColors . push ( rgb_color ) ;
63
+ ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
64
+ ctx . drawImage ( img , 0 , 0 ) ;
65
+
66
+ drawAllPolygons ( ) ;
67
+ points = [ ] ;
68
+
69
+ // dont choose a color that has already been chosen
70
+ var remaining_choices = color_choices . filter ( function ( x ) {
71
+ return ! masterColors . includes ( x ) ;
72
+ } ) ;
73
+
74
+ if ( remaining_choices . length == 0 ) {
75
+ remaining_choices = color_choices ;
76
+ }
77
+
78
+ rgb_color = remaining_choices [ Math . floor ( Math . random ( ) * remaining_choices . length ) ] ;
79
+ }
80
+
56
81
// placeholder image
57
82
img . src = 'https://assets.website-files.com/5f6bc60e665f54545a1e52a5/63d3f236a6f0dae14cdf0063_drag-image-here.png' ;
58
83
img . onload = function ( ) {
@@ -70,7 +95,7 @@ function drawLine(x1, y1, x2, y2) {
70
95
ctx . lineWidth = 5 ;
71
96
ctx . moveTo ( x1 , y1 ) ;
72
97
ctx . lineTo ( x2 , y2 ) ;
73
- ctx . stroke ( ) ;
98
+ // ctx.stroke();
74
99
}
75
100
76
101
function getScaledCoords ( e ) {
@@ -80,50 +105,6 @@ function getScaledCoords(e) {
80
105
return [ x / scaleFactor , y / scaleFactor ] ;
81
106
}
82
107
83
- function drawCurrentPolygon ( cursorX , cursorY ) {
84
- //ctx.clearRect(0, 0, canvas.width, canvas.height);
85
- ctx . drawImage ( img , 0 , 0 ) ;
86
- for ( var i = 0 ; i < points . length - 1 ; i ++ ) {
87
- // draw arc around each point
88
- ctx . beginPath ( ) ;
89
- ctx . strokeStyle = rgb_color ;
90
- ctx . arc ( points [ i ] [ 0 ] , points [ i ] [ 1 ] , 5 , 0 , 2 * Math . PI ) ;
91
- // fill with white
92
- ctx . fillStyle = 'white' ;
93
- ctx . fill ( ) ;
94
- ctx . stroke ( ) ;
95
- drawLine ( points [ i ] [ 0 ] , points [ i ] [ 1 ] , points [ i + 1 ] [ 0 ] , points [ i + 1 ] [ 1 ] ) ;
96
- }
97
-
98
- if ( ( points . length > 0 && drawMode == "polygon" ) || ( points . length > 0 && points . length < 2 && drawMode == "line" ) ) {
99
- ctx . beginPath ( ) ;
100
- ctx . strokeStyle = rgb_color ;
101
- ctx . arc ( points [ i ] [ 0 ] , points [ i ] [ 1 ] , 5 , 0 , 2 * Math . PI ) ;
102
- // fill with white
103
- ctx . fillStyle = 'white' ;
104
- ctx . fill ( ) ;
105
- ctx . stroke ( ) ;
106
-
107
- if ( cursorX && cursorY ) {
108
- drawLine ( points [ points . length - 1 ] [ 0 ] , points [ points . length - 1 ] [ 1 ] , cursorX , cursorY ) ;
109
- }
110
-
111
- if ( points . length == 2 && drawMode == "line" ) {
112
- console . log ( "line" ) ;
113
- // draw arc around each point
114
- ctx . beginPath ( ) ;
115
- ctx . strokeStyle = rgb_color ;
116
- ctx . arc ( points [ 0 ] [ 0 ] , points [ 0 ] [ 1 ] , 5 , 0 , 2 * Math . PI ) ;
117
- // fill with white
118
- ctx . fillStyle = 'white' ;
119
- ctx . fill ( ) ;
120
- ctx . stroke ( ) ;
121
- masterPoints . push ( points ) ;
122
- points = [ ] ;
123
- }
124
- }
125
- }
126
-
127
108
function drawAllPolygons ( ) {
128
109
// draw all points for previous regions
129
110
for ( var i = 0 ; i < masterPoints . length ; i ++ ) {
@@ -133,6 +114,17 @@ function drawAllPolygons () {
133
114
for ( var j = 1 ; j < newpoints . length ; j ++ ) {
134
115
// draw all lines
135
116
drawLine ( newpoints [ j - 1 ] [ 0 ] , newpoints [ j - 1 ] [ 1 ] , newpoints [ j ] [ 0 ] , newpoints [ j ] [ 1 ] ) ;
117
+
118
+ // fill
119
+ ctx . beginPath ( ) ;
120
+ ctx . fillStyle = opaque_color ;
121
+ ctx . moveTo ( newpoints [ 0 ] [ 0 ] , newpoints [ 0 ] [ 1 ] ) ;
122
+ for ( var j = 1 ; j < newpoints . length ; j ++ ) {
123
+ ctx . lineTo ( newpoints [ j ] [ 0 ] , newpoints [ j ] [ 1 ] ) ;
124
+ }
125
+ ctx . closePath ( ) ;
126
+ ctx . fill ( ) ;
127
+ ctx . stroke ( ) ;
136
128
}
137
129
drawLine ( newpoints [ newpoints . length - 1 ] [ 0 ] , newpoints [ newpoints . length - 1 ] [ 1 ] , newpoints [ 0 ] [ 0 ] , newpoints [ 0 ] [ 1 ] ) ;
138
130
// draw arc around each point
@@ -145,15 +137,7 @@ function drawAllPolygons () {
145
137
ctx . fill ( ) ;
146
138
ctx . stroke ( ) ;
147
139
}
148
- // fill
149
- ctx . beginPath ( ) ;
150
- ctx . fillStyle = opaque_color ;
151
- ctx . moveTo ( newpoints [ 0 ] [ 0 ] , newpoints [ 0 ] [ 1 ] ) ;
152
- for ( var j = 1 ; j < newpoints . length ; j ++ ) {
153
- ctx . lineTo ( newpoints [ j ] [ 0 ] , newpoints [ j ] [ 1 ] ) ;
154
- }
155
- ctx . closePath ( ) ;
156
- ctx . fill ( ) ;
140
+
157
141
}
158
142
}
159
143
@@ -166,6 +150,11 @@ function getParentPoints () {
166
150
return parentPoints ;
167
151
}
168
152
153
+ window . addEventListener ( 'keyup' , function ( e ) {
154
+ if ( e . key === 'Shift' ) {
155
+ constrainAngles = false ;
156
+ }
157
+ } ) ;
169
158
170
159
document . querySelector ( '#clipboard' ) . addEventListener ( 'click' , function ( e ) {
171
160
e . preventDefault ( ) ;
@@ -198,12 +187,54 @@ canvas.addEventListener('mousemove', function(e) {
198
187
// update x y coords
199
188
var xcoord = document . querySelector ( '#x' ) ;
200
189
var ycoord = document . querySelector ( '#y' ) ;
190
+
191
+ if ( constrainAngles ) {
192
+ var lastPoint = points [ points . length - 1 ] ;
193
+ var dx = x - lastPoint [ 0 ] ;
194
+ var dy = y - lastPoint [ 1 ] ;
195
+ var angle = Math . atan2 ( dy , dx ) ;
196
+ var length = Math . sqrt ( dx * dx + dy * dy ) ;
197
+ const snappedAngle = Math . round ( angle / radiansPer45Degrees ) * radiansPer45Degrees ;
198
+ var new_x = lastPoint [ 0 ] + length * Math . cos ( snappedAngle ) ;
199
+ var new_y = lastPoint [ 1 ] + length * Math . sin ( snappedAngle ) ;
200
+ x = Math . round ( new_x ) ;
201
+ y = Math . round ( new_y ) ;
202
+ }
203
+
201
204
xcoord . innerHTML = x ;
202
205
ycoord . innerHTML = y ;
203
206
204
207
if ( canvas . style . cursor == 'crosshair' ) {
205
- drawCurrentPolygon ( x , y )
208
+ ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
209
+ ctx . drawImage ( img , 0 , 0 ) ;
210
+
206
211
drawAllPolygons ( ) ;
212
+
213
+ for ( var i = 0 ; i < points . length - 1 ; i ++ ) {
214
+ ctx . strokeStyle = rgb_color ;
215
+ drawLine ( points [ i ] [ 0 ] , points [ i ] [ 1 ] , points [ i + 1 ] [ 0 ] , points [ i + 1 ] [ 1 ] ) ;
216
+ ctx . stroke ( ) ;
217
+ // draw arc around each point
218
+ ctx . beginPath ( ) ;
219
+ ctx . arc ( points [ i ] [ 0 ] , points [ i ] [ 1 ] , 5 , 0 , 2 * Math . PI ) ;
220
+ // fill with white
221
+ ctx . fillStyle = 'white' ;
222
+ ctx . fill ( ) ;
223
+ ctx . stroke ( ) ;
224
+ }
225
+
226
+
227
+ if ( ( points . length > 0 && drawMode == "polygon" ) || ( points . length > 0 && points . length < 2 && drawMode == "line" ) ) {
228
+ ctx . strokeStyle = rgb_color ;
229
+ drawLine ( points [ points . length - 1 ] [ 0 ] , points [ points . length - 1 ] [ 1 ] , x , y ) ;
230
+ ctx . stroke ( ) ; // new
231
+ ctx . beginPath ( ) ;
232
+ ctx . arc ( points [ i ] [ 0 ] , points [ i ] [ 1 ] , 5 , 0 , 2 * Math . PI ) ;
233
+ // fill with white
234
+ ctx . fillStyle = 'white' ;
235
+ ctx . fill ( ) ;
236
+ ctx . stroke ( ) ;
237
+ }
207
238
}
208
239
} ) ;
209
240
@@ -309,37 +340,59 @@ canvas.addEventListener('click', function(e) {
309
340
x = Math . round ( x ) ;
310
341
y = Math . round ( y ) ;
311
342
312
- // If starting point os clicked, we complete the polygon
313
- if ( drawMode === 'polygon' && points . length > 1 ) {
314
- const [ firstPointX , firstPointY ] = points [ 0 ]
315
- const overlapDistance = 15
316
- const isXOverlaped = Math . abs ( x - firstPointX ) <= overlapDistance
317
- const isYOverlaped = Math . abs ( y - firstPointY ) <= overlapDistance
318
- if ( isXOverlaped && isYOverlaped ) {
319
- completeCurrentPolygon ( )
320
- return
343
+ if ( constrainAngles ) {
344
+ var lastPoint = points [ points . length - 1 ] ;
345
+ var dx = x - lastPoint [ 0 ] ;
346
+ var dy = y - lastPoint [ 1 ] ;
347
+ var angle = Math . atan2 ( dy , dx ) ;
348
+ var length = Math . sqrt ( dx * dx + dy * dy ) ;
349
+ const snappedAngle = Math . round ( angle / radiansPer45Degrees ) * radiansPer45Degrees ;
350
+ var new_x = lastPoint [ 0 ] + length * Math . cos ( snappedAngle ) ;
351
+ var new_y = lastPoint [ 1 ] + length * Math . sin ( snappedAngle ) ;
352
+ x = Math . round ( new_x ) ;
353
+ y = Math . round ( new_y ) ;
354
+ }
355
+
356
+ if ( points . length > 2 && drawMode == "polygon" ) {
357
+ distX = x - points [ 0 ] [ 0 ] ;
358
+ distY = y - points [ 0 ] [ 1 ] ;
359
+ // stroke is 3px and centered on the circle (i.e. 1/2 * 3px) and arc radius is
360
+ if ( Math . sqrt ( distX * distX + distY * distY ) <= 6.5 ) {
361
+ closePath ( ) ;
362
+ return ;
321
363
}
322
364
}
323
365
324
366
points . push ( [ x , y ] ) ;
325
367
326
- // if line mode and two points have been drawn, add to masterPoints
327
- if ( drawMode == 'line' && points . length == 2 ) {
328
- masterPoints . push ( points ) ;
329
- points = [ ] ;
330
- }
331
-
332
368
ctx . beginPath ( ) ;
333
369
ctx . strokeStyle = rgb_color ;
334
- // add rgb_color to masterColors
335
-
336
- if ( masterColors . length == 0 ) {
337
- masterColors . push ( rgb_color ) ;
370
+ ctx . arc ( x , y , 5 , 0 , 2 * Math . PI ) ;
371
+ // fill with white
372
+ ctx . fillStyle = 'white' ;
373
+ ctx . fill ( ) ;
374
+ ctx . stroke ( ) ;
375
+
376
+ if ( drawMode == "line" && points . length == 2 ) {
377
+ closePath ( ) ;
378
+ }
379
+ else {
380
+ ctx . beginPath ( ) ;
381
+ ctx . strokeStyle = rgb_color ;
338
382
}
383
+
384
+ // ctx.arc(x, y, 155, 0, 2 * Math.PI);
385
+ // concat all points into one array
386
+ var parentPoints = [ ] ;
339
387
340
- ctx . arc ( x , y , 155 , 0 , 2 * Math . PI ) ;
388
+ for ( var i = 0 ; i < masterPoints . length ; i ++ ) {
389
+ parentPoints . push ( masterPoints [ i ] ) ;
390
+ }
391
+ // add "points"
392
+ if ( points . length > 0 ) {
393
+ parentPoints . push ( points ) ;
394
+ }
341
395
342
- var parentPoints = getParentPoints ( ) ;
343
396
writePoints ( parentPoints ) ;
344
397
} ) ;
345
398
@@ -374,8 +427,9 @@ document.addEventListener('keydown', function(e) {
374
427
} )
375
428
376
429
function draw ( ) {
377
- drawCurrentPolygon ( )
430
+
378
431
drawAllPolygons ( )
432
+ drawCurrentPolygon ( )
379
433
var parentPoints = getParentPoints ( )
380
434
writePoints ( parentPoints )
381
435
}
@@ -415,6 +469,7 @@ function clearAll() {
415
469
416
470
points = [ ]
417
471
masterPoints = [ ]
472
+ masterColors = [ ]
418
473
document . querySelector ( '#json' ) . innerHTML = ''
419
474
document . querySelector ( '#python' ) . innerHTML = ''
420
475
}
@@ -466,6 +521,10 @@ window.addEventListener('keydown', function(e) {
466
521
undo ( )
467
522
}
468
523
524
+ if ( e . key === 'Shift' ) {
525
+ constrainAngles = true ;
526
+ }
527
+
469
528
if ( e . key === 'Escape' ) {
470
529
discardCurrentPolygon ( )
471
530
}
0 commit comments