@@ -42,6 +42,10 @@ var showNormalized = false;
42
42
var modeMessage = document . querySelector ( '#mode' ) ;
43
43
// var coords = document.querySelector('#coords');
44
44
45
+ var editMode = false ;
46
+ var selectedPointIndex = - 1 ;
47
+ var selectedPolygonIndex = - 1 ;
48
+
45
49
function blitCachedCanvas ( ) {
46
50
mainCtx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
47
51
mainCtx . drawImage ( offScreenCanvas , 0 , 0 ) ;
@@ -185,6 +189,28 @@ function getParentPoints() {
185
189
return parentPoints ;
186
190
}
187
191
192
+ function findClosestPoint ( x , y ) {
193
+ let minDist = Infinity ;
194
+ let closestPoint = null ;
195
+ let polygonIndex = - 1 ;
196
+ let pointIndex = - 1 ;
197
+
198
+ for ( let i = 0 ; i < masterPoints . length ; i ++ ) {
199
+ for ( let j = 0 ; j < masterPoints [ i ] . length ; j ++ ) {
200
+ const [ px , py ] = masterPoints [ i ] [ j ] ;
201
+ const dist = Math . sqrt ( ( x - px ) ** 2 + ( y - py ) ** 2 ) ;
202
+ if ( dist < minDist && dist < 10 / scaleFactor ) { // grab radius
203
+ minDist = dist ;
204
+ closestPoint = [ px , py ] ;
205
+ polygonIndex = i ;
206
+ pointIndex = j ;
207
+ }
208
+ }
209
+ }
210
+
211
+ return { point : closestPoint , polygonIndex, pointIndex } ;
212
+ }
213
+
188
214
window . addEventListener ( 'keyup' , function ( e ) {
189
215
if ( e . key === 'Shift' ) {
190
216
constrainAngles = false ;
@@ -218,19 +244,16 @@ canvas.addEventListener('mouseleave', function(e) {
218
244
ycoord . innerHTML = '' ;
219
245
} ) ;
220
246
221
- // on canvas hover, if cursor is crosshair, draw line from last point to cursor
222
247
canvas . addEventListener ( 'mousemove' , function ( e ) {
223
- var x = getScaledCoords ( e ) [ 0 ] ;
224
- var y = getScaledCoords ( e ) [ 1 ] ;
225
- // round
248
+ var [ x , y ] = getScaledCoords ( e ) ;
226
249
x = Math . round ( x ) ;
227
250
y = Math . round ( y ) ;
228
251
229
252
// update x y coords
230
253
var xcoord = document . querySelector ( '#x' ) ;
231
254
var ycoord = document . querySelector ( '#y' ) ;
232
255
233
- if ( constrainAngles ) {
256
+ if ( constrainAngles && points . length > 0 ) {
234
257
var lastPoint = points [ points . length - 1 ] ;
235
258
var dx = x - lastPoint [ 0 ] ;
236
259
var dy = y - lastPoint [ 1 ] ;
@@ -258,6 +281,7 @@ canvas.addEventListener('mousemove', function(e) {
258
281
ctx . lineJoin = 'bevel' ;
259
282
ctx . fillStyle = 'white' ;
260
283
284
+ // if cursor is crosshair, draw line from last point to cursor
261
285
if ( canvas . style . cursor == 'crosshair' ) {
262
286
blitCachedCanvas ( ) ;
263
287
@@ -284,6 +308,13 @@ canvas.addEventListener('mousemove', function(e) {
284
308
drawNode ( ctx , points [ i ] [ 0 ] , points [ i ] [ 1 ] ) ;
285
309
}
286
310
}
311
+
312
+ if ( editMode && selectedPointIndex !== - 1 ) {
313
+ masterPoints [ selectedPolygonIndex ] [ selectedPointIndex ] = [ x , y ] ;
314
+ drawAllPolygons ( offScreenCtx ) ;
315
+ blitCachedCanvas ( ) ;
316
+ writePoints ( getParentPoints ( ) ) ;
317
+ }
287
318
} ) ;
288
319
289
320
canvas . addEventListener ( 'drop' , function ( e ) {
@@ -364,57 +395,74 @@ function writePoints(parentPoints) {
364
395
document . querySelector ( '#json' ) . innerHTML = json_template ;
365
396
}
366
397
367
- canvas . addEventListener ( 'click' , function ( e ) {
368
- canvas . style . cursor = 'crosshair' ;
369
-
370
- var x = getScaledCoords ( e ) [ 0 ] ;
371
- var y = getScaledCoords ( e ) [ 1 ] ;
398
+ canvas . addEventListener ( 'mousedown' , function ( e ) {
399
+ var [ x , y ] = getScaledCoords ( e ) ;
372
400
x = Math . round ( x ) ;
373
401
y = Math . round ( y ) ;
374
402
375
- if ( constrainAngles ) {
376
- var lastPoint = points [ points . length - 1 ] ;
377
- var dx = x - lastPoint [ 0 ] ;
378
- var dy = y - lastPoint [ 1 ] ;
379
- var angle = Math . atan2 ( dy , dx ) ;
380
- var length = Math . sqrt ( dx * dx + dy * dy ) ;
381
- const snappedAngle = Math . round ( angle / radiansPer45Degrees ) * radiansPer45Degrees ;
382
- var new_x = lastPoint [ 0 ] + length * Math . cos ( snappedAngle ) ;
383
- var new_y = lastPoint [ 1 ] + length * Math . sin ( snappedAngle ) ;
384
- x = Math . round ( new_x ) ;
385
- y = Math . round ( new_y ) ;
386
- }
403
+ if ( editMode ) {
404
+ const { point, polygonIndex, pointIndex } = findClosestPoint ( x , y ) ;
405
+ if ( point ) {
406
+ selectedPointIndex = pointIndex ;
407
+ selectedPolygonIndex = polygonIndex ;
408
+ canvas . style . cursor = 'grabbing' ;
409
+ }
410
+ } else {
411
+ // click handling for drawing mode
412
+ canvas . style . cursor = 'crosshair' ;
413
+
414
+ if ( constrainAngles && points . length > 0 ) {
415
+ var lastPoint = points [ points . length - 1 ] ;
416
+ var dx = x - lastPoint [ 0 ] ;
417
+ var dy = y - lastPoint [ 1 ] ;
418
+ var angle = Math . atan2 ( dy , dx ) ;
419
+ var length = Math . sqrt ( dx * dx + dy * dy ) ;
420
+ const snappedAngle = Math . round ( angle / radiansPer45Degrees ) * radiansPer45Degrees ;
421
+ var new_x = lastPoint [ 0 ] + length * Math . cos ( snappedAngle ) ;
422
+ var new_y = lastPoint [ 1 ] + length * Math . sin ( snappedAngle ) ;
423
+ x = Math . round ( new_x ) ;
424
+ y = Math . round ( new_y ) ;
425
+ }
387
426
388
- if ( points . length > 2 && drawMode == "polygon" ) {
389
- distX = x - points [ 0 ] [ 0 ] ;
390
- distY = y - points [ 0 ] [ 1 ] ;
391
- // stroke is 3px and centered on the circle (i.e. 1/2 * 3px) and arc radius is
392
- if ( Math . sqrt ( distX * distX + distY * distY ) <= 6.5 ) {
393
- onPathClose ( ) ;
394
- return ;
427
+ if ( points . length > 2 && drawMode == "polygon" ) {
428
+ distX = x - points [ 0 ] [ 0 ] ;
429
+ distY = y - points [ 0 ] [ 1 ] ;
430
+ // stroke is 3px and centered on the circle (i.e. 1/2 * 3px) and arc radius is
431
+ if ( Math . sqrt ( distX * distX + distY * distY ) <= 6.5 ) {
432
+ onPathClose ( ) ;
433
+ return ;
434
+ }
395
435
}
396
- }
397
436
398
- points . push ( [ x , y ] ) ;
437
+ points . push ( [ x , y ] ) ;
399
438
400
- drawNode ( mainCtx , x , y , rgb_color ) ;
439
+ drawNode ( mainCtx , x , y , rgb_color ) ;
401
440
402
- if ( drawMode == "line" && points . length == 2 ) {
403
- onPathClose ( ) ;
404
- }
441
+ if ( drawMode == "line" && points . length == 2 ) {
442
+ onPathClose ( ) ;
443
+ }
405
444
406
- // concat all points into one array
407
- var parentPoints = [ ] ;
445
+ // concat all points into one array
446
+ var parentPoints = [ ] ;
408
447
409
- for ( var i = 0 ; i < masterPoints . length ; i ++ ) {
410
- parentPoints . push ( masterPoints [ i ] ) ;
411
- }
412
- // add "points"
413
- if ( points . length > 0 ) {
414
- parentPoints . push ( points ) ;
448
+ for ( var i = 0 ; i < masterPoints . length ; i ++ ) {
449
+ parentPoints . push ( masterPoints [ i ] ) ;
450
+ }
451
+ // add "points"
452
+ if ( points . length > 0 ) {
453
+ parentPoints . push ( points ) ;
454
+ }
455
+
456
+ writePoints ( parentPoints ) ;
415
457
}
458
+ } ) ;
416
459
417
- writePoints ( parentPoints ) ;
460
+ canvas . addEventListener ( 'mouseup' , function ( e ) {
461
+ if ( editMode ) {
462
+ selectedPointIndex = - 1 ;
463
+ selectedPolygonIndex = - 1 ;
464
+ canvas . style . cursor = 'move' ;
465
+ }
418
466
} ) ;
419
467
420
468
document . querySelector ( '#normalize-checkbox' ) . addEventListener ( 'change' , function ( e ) {
@@ -425,11 +473,19 @@ document.querySelector('#normalize-checkbox').addEventListener('change', functio
425
473
426
474
function setDrawMode ( mode ) {
427
475
drawMode = mode ;
476
+ setEditMode ( false ) ;
428
477
canvas . style . cursor = 'crosshair' ;
429
478
document . querySelectorAll ( '.t-mode' ) . forEach ( el => el . classList . remove ( 'active' ) ) ;
430
479
document . querySelector ( `#mode-${ mode } ` ) . classList . add ( 'active' ) ;
431
480
}
432
481
482
+ function setEditMode ( editEnabled ) {
483
+ editMode = editEnabled ;
484
+ canvas . style . cursor = editEnabled ? 'move' : 'crosshair' ;
485
+ document . querySelectorAll ( '.t-mode' ) . forEach ( el => el . classList . remove ( 'active' ) ) ;
486
+ document . querySelector ( `#mode-${ editEnabled ? 'edit' : drawMode } ` ) . classList . add ( 'active' ) ;
487
+ }
488
+
433
489
document . querySelector ( '#mode-polygon' ) . addEventListener ( 'click' , function ( e ) {
434
490
setDrawMode ( 'polygon' ) ;
435
491
} )
@@ -438,14 +494,21 @@ document.querySelector('#mode-line').addEventListener('click', function(e) {
438
494
setDrawMode ( 'line' ) ;
439
495
} )
440
496
497
+ document . querySelector ( '#mode-edit' ) . addEventListener ( 'click' , function ( e ) {
498
+ setEditMode ( true ) ;
499
+ } ) ;
500
+
441
501
document . addEventListener ( 'keydown' , function ( e ) {
442
502
if ( e . key == 'l' || e . key == 'L' ) {
443
503
setDrawMode ( 'line' ) ;
444
504
}
445
505
if ( e . key == 'p' || e . key == 'P' ) {
446
506
setDrawMode ( 'polygon' ) ;
447
507
}
448
- } )
508
+ if ( e . key == 'e' || e . key == 'E' ) {
509
+ setEditMode ( true ) ;
510
+ }
511
+ } ) ;
449
512
450
513
function rewritePoints ( ) {
451
514
var parentPoints = getParentPoints ( ) ;
0 commit comments