Skip to content

Commit 8d54df5

Browse files
authored
Merge branch 'main' into fullscreen-mode
2 parents 3fb94b0 + f757c2b commit 8d54df5

File tree

2 files changed

+128
-61
lines changed

2 files changed

+128
-61
lines changed

index.html

+9-2
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,19 @@ <h2>JSON Points</h2>
7878
</span>
7979
</div>
8080
<div class="t-icon t-mode" id="mode-line">
81-
<i class="fa-solid fa-arrows-left-right"></i>
81+
<i class="fa-solid fa-lines-leaning"></i>
8282
<span class="ti-caption">
8383
<span>Line Mode</span>
8484
<span>(L)</span>
8585
</span>
8686
</div>
87+
<div class="t-icon t-mode" id="mode-edit">
88+
<i class="fa-solid fa-up-down-left-right"></i>
89+
<span class="ti-caption">
90+
<span>Edit Mode</span>
91+
<span>(E)</span>
92+
</span>
93+
</div>
8794
<div class="t-divider"></div>
8895
<div class="t-icon" id="undo">
8996
<i class="fa-solid fa-rotate-left"></i>
@@ -100,7 +107,7 @@ <h2>JSON Points</h2>
100107
</span>
101108
</div>
102109
<div class="t-icon" id="clear">
103-
<i class="fa-solid fa-trash-can"></i>
110+
<i class="fa-solid fa-trash"></i>
104111
<span class="ti-caption">
105112
<span>Clear all polygons</span>
106113
<span>(Ctrl/⌘-E)</span>

script.js

+119-59
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,15 @@ var showNormalized = false;
4242
var modeMessage = document.querySelector('#mode');
4343
// var coords = document.querySelector('#coords');
4444

45+
4546
var isFullscreen = false;
4647
var taskbarAndCanvas = document.querySelector('.right');
4748

49+
var editMode = false;
50+
var selectedPointIndex = -1;
51+
var selectedPolygonIndex = -1;
52+
53+
4854
function blitCachedCanvas() {
4955
mainCtx.clearRect(0, 0, canvas.width, canvas.height);
5056
mainCtx.drawImage(offScreenCanvas, 0, 0);
@@ -188,6 +194,28 @@ function getParentPoints() {
188194
return parentPoints;
189195
}
190196

197+
function findClosestPoint(x, y) {
198+
let minDist = Infinity;
199+
let closestPoint = null;
200+
let polygonIndex = -1;
201+
let pointIndex = -1;
202+
203+
for (let i = 0; i < masterPoints.length; i++) {
204+
for (let j = 0; j < masterPoints[i].length; j++) {
205+
const [px, py] = masterPoints[i][j];
206+
const dist = Math.sqrt((x - px) ** 2 + (y - py) ** 2);
207+
if (dist < minDist && dist < 10 / scaleFactor) { // grab radius
208+
minDist = dist;
209+
closestPoint = [px, py];
210+
polygonIndex = i;
211+
pointIndex = j;
212+
}
213+
}
214+
}
215+
216+
return { point: closestPoint, polygonIndex, pointIndex };
217+
}
218+
191219
window.addEventListener('keyup', function(e) {
192220
if (e.key === 'Shift') {
193221
constrainAngles = false;
@@ -221,19 +249,16 @@ canvas.addEventListener('mouseleave', function(e) {
221249
ycoord.innerHTML = '';
222250
});
223251

224-
// on canvas hover, if cursor is crosshair, draw line from last point to cursor
225252
canvas.addEventListener('mousemove', function(e) {
226-
var x = getScaledCoords(e)[0];
227-
var y = getScaledCoords(e)[1];
228-
// round
253+
var [x, y] = getScaledCoords(e);
229254
x = Math.round(x);
230255
y = Math.round(y);
231256

232257
// update x y coords
233258
var xcoord = document.querySelector('#x');
234259
var ycoord = document.querySelector('#y');
235260

236-
if(constrainAngles) {
261+
if(constrainAngles && points.length > 0) {
237262
var lastPoint = points[points.length - 1];
238263
var dx = x - lastPoint[0];
239264
var dy = y - lastPoint[1];
@@ -261,6 +286,7 @@ canvas.addEventListener('mousemove', function(e) {
261286
ctx.lineJoin = 'bevel';
262287
ctx.fillStyle = 'white';
263288

289+
// if cursor is crosshair, draw line from last point to cursor
264290
if (canvas.style.cursor == 'crosshair') {
265291
blitCachedCanvas();
266292

@@ -287,30 +313,32 @@ canvas.addEventListener('mousemove', function(e) {
287313
drawNode(ctx, points[i][0], points[i][1]);
288314
}
289315
}
316+
317+
if (editMode && selectedPointIndex !== -1) {
318+
masterPoints[selectedPolygonIndex][selectedPointIndex] = [x, y];
319+
drawAllPolygons(offScreenCtx);
320+
blitCachedCanvas();
321+
writePoints(getParentPoints());
322+
}
290323
});
291324

292325
canvas.addEventListener('drop', function(e) {
293326
e.preventDefault();
294327
var file = e.dataTransfer.files[0];
328+
329+
// only allow image files
330+
var supportedImageTypes = ['image/png', 'image/jpeg', 'image/jpg', 'image/webp'];
331+
if (!supportedImageTypes.includes(file.type)) {
332+
alert('Only PNG, JPEG, JPG, and WebP files are allowed.');
333+
return;
334+
}
335+
295336
var reader = new FileReader();
296-
297337
reader.onload = function(event) {
298-
// only allow image files
299338
img.src = event.target.result;
300339
};
301340
reader.readAsDataURL(file);
302341

303-
var mime_type = file.type;
304-
305-
if (
306-
mime_type != 'image/png' &&
307-
mime_type != 'image/jpeg' &&
308-
mime_type != 'image/jpg'
309-
) {
310-
alert('Only PNG, JPEG, and JPG files are allowed.');
311-
return;
312-
}
313-
314342
img.onload = function() {
315343
scaleFactor = 0.25;
316344
canvas.style.width = img.width * scaleFactor + 'px';
@@ -352,7 +380,7 @@ function writePoints(parentPoints) {
352380

353381
if (!parentPoints.length) {
354382
document.querySelector('#python').innerHTML = '';
355-
document.querySelector('#json').innerHTML;
383+
document.querySelector('#json').innerHTML = '';
356384
return;
357385
}
358386

@@ -372,57 +400,74 @@ function writePoints(parentPoints) {
372400
document.querySelector('#json').innerHTML = json_template;
373401
}
374402

375-
canvas.addEventListener('click', function(e) {
376-
canvas.style.cursor = 'crosshair';
377-
378-
var x = getScaledCoords(e)[0];
379-
var y = getScaledCoords(e)[1];
403+
canvas.addEventListener('mousedown', function(e) {
404+
var [x, y] = getScaledCoords(e);
380405
x = Math.round(x);
381406
y = Math.round(y);
382407

383-
if(constrainAngles) {
384-
var lastPoint = points[points.length - 1];
385-
var dx = x - lastPoint[0];
386-
var dy = y - lastPoint[1];
387-
var angle = Math.atan2(dy, dx);
388-
var length = Math.sqrt(dx * dx + dy * dy);
389-
const snappedAngle = Math.round(angle / radiansPer45Degrees) * radiansPer45Degrees;
390-
var new_x = lastPoint[0] + length * Math.cos(snappedAngle);
391-
var new_y = lastPoint[1] + length * Math.sin(snappedAngle);
392-
x = Math.round(new_x);
393-
y = Math.round(new_y);
394-
}
408+
if (editMode) {
409+
const { point, polygonIndex, pointIndex } = findClosestPoint(x, y);
410+
if (point) {
411+
selectedPointIndex = pointIndex;
412+
selectedPolygonIndex = polygonIndex;
413+
canvas.style.cursor = 'grabbing';
414+
}
415+
} else {
416+
// click handling for drawing mode
417+
canvas.style.cursor = 'crosshair';
418+
419+
if(constrainAngles && points.length > 0) {
420+
var lastPoint = points[points.length - 1];
421+
var dx = x - lastPoint[0];
422+
var dy = y - lastPoint[1];
423+
var angle = Math.atan2(dy, dx);
424+
var length = Math.sqrt(dx * dx + dy * dy);
425+
const snappedAngle = Math.round(angle / radiansPer45Degrees) * radiansPer45Degrees;
426+
var new_x = lastPoint[0] + length * Math.cos(snappedAngle);
427+
var new_y = lastPoint[1] + length * Math.sin(snappedAngle);
428+
x = Math.round(new_x);
429+
y = Math.round(new_y);
430+
}
395431

396-
if (points.length > 2 && drawMode == "polygon") {
397-
distX = x - points[0][0];
398-
distY = y - points[0][1];
399-
// stroke is 3px and centered on the circle (i.e. 1/2 * 3px) and arc radius is
400-
if(Math.sqrt(distX * distX + distY * distY) <= 6.5) {
401-
onPathClose();
402-
return;
432+
if (points.length > 2 && drawMode == "polygon") {
433+
distX = x - points[0][0];
434+
distY = y - points[0][1];
435+
// stroke is 3px and centered on the circle (i.e. 1/2 * 3px) and arc radius is
436+
if(Math.sqrt(distX * distX + distY * distY) <= 6.5) {
437+
onPathClose();
438+
return;
439+
}
403440
}
404-
}
405441

406-
points.push([x, y]);
442+
points.push([x, y]);
407443

408-
drawNode(mainCtx, x, y, rgb_color);
444+
drawNode(mainCtx, x, y, rgb_color);
409445

410-
if(drawMode == "line" && points.length == 2) {
411-
onPathClose();
412-
}
446+
if(drawMode == "line" && points.length == 2) {
447+
onPathClose();
448+
}
413449

414-
// concat all points into one array
415-
var parentPoints = [];
450+
// concat all points into one array
451+
var parentPoints = [];
416452

417-
for (var i = 0; i < masterPoints.length; i++) {
418-
parentPoints.push(masterPoints[i]);
419-
}
420-
// add "points"
421-
if(points.length > 0) {
422-
parentPoints.push(points);
453+
for (var i = 0; i < masterPoints.length; i++) {
454+
parentPoints.push(masterPoints[i]);
455+
}
456+
// add "points"
457+
if(points.length > 0) {
458+
parentPoints.push(points);
459+
}
460+
461+
writePoints(parentPoints);
423462
}
463+
});
424464

425-
writePoints(parentPoints);
465+
canvas.addEventListener('mouseup', function(e) {
466+
if (editMode) {
467+
selectedPointIndex = -1;
468+
selectedPolygonIndex = -1;
469+
canvas.style.cursor = 'move';
470+
}
426471
});
427472

428473
document.querySelector('#normalize-checkbox').addEventListener('change', function(e) {
@@ -433,11 +478,19 @@ document.querySelector('#normalize-checkbox').addEventListener('change', functio
433478

434479
function setDrawMode(mode) {
435480
drawMode = mode;
481+
setEditMode(false);
436482
canvas.style.cursor = 'crosshair';
437483
document.querySelectorAll('.t-mode').forEach(el => el.classList.remove('active'));
438484
document.querySelector(`#mode-${mode}`).classList.add('active');
439485
}
440486

487+
function setEditMode(editEnabled) {
488+
editMode = editEnabled;
489+
canvas.style.cursor = editEnabled ? 'move' : 'crosshair';
490+
document.querySelectorAll('.t-mode').forEach(el => el.classList.remove('active'));
491+
document.querySelector(`#mode-${editEnabled ? 'edit' : drawMode}`).classList.add('active');
492+
}
493+
441494
document.querySelector('#mode-polygon').addEventListener('click', function(e) {
442495
setDrawMode('polygon');
443496
})
@@ -446,14 +499,21 @@ document.querySelector('#mode-line').addEventListener('click', function(e) {
446499
setDrawMode('line');
447500
})
448501

502+
document.querySelector('#mode-edit').addEventListener('click', function(e) {
503+
setEditMode(true);
504+
});
505+
449506
document.addEventListener('keydown', function(e) {
450507
if (e.key == 'l' || e.key == 'L') {
451508
setDrawMode('line');
452509
}
453510
if (e.key == 'p' || e.key == 'P') {
454511
setDrawMode('polygon');
455512
}
456-
})
513+
if (e.key == 'e' || e.key == 'E') {
514+
setEditMode(true);
515+
}
516+
});
457517

458518
function rewritePoints() {
459519
var parentPoints = getParentPoints();

0 commit comments

Comments
 (0)