Spaces:
Running
Running
highlight added
Browse files
comic_panel_extractor/static/annotator.html
CHANGED
|
@@ -473,7 +473,7 @@
|
|
| 473 |
.point-edit-input {
|
| 474 |
flex: 1;
|
| 475 |
padding: 2px 4px;
|
| 476 |
-
font-size:
|
| 477 |
border: 1px solid #d1d5db;
|
| 478 |
border-radius: 3px;
|
| 479 |
width: 50px;
|
|
@@ -485,7 +485,7 @@
|
|
| 485 |
border: none;
|
| 486 |
border-radius: 3px;
|
| 487 |
padding: 2px 6px;
|
| 488 |
-
font-size:
|
| 489 |
cursor: pointer;
|
| 490 |
min-width: 20px;
|
| 491 |
}
|
|
@@ -493,6 +493,25 @@
|
|
| 493 |
.point-delete-btn:hover {
|
| 494 |
background: #e53e3e;
|
| 495 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 496 |
</style>
|
| 497 |
</head>
|
| 498 |
|
|
@@ -767,6 +786,9 @@
|
|
| 767 |
this.clickStartTime = 0;
|
| 768 |
this.modeIndicatorTimeout = null;
|
| 769 |
|
|
|
|
|
|
|
|
|
|
| 770 |
this.init();
|
| 771 |
}
|
| 772 |
|
|
@@ -954,6 +976,7 @@
|
|
| 954 |
this.waitingForDrag = false;
|
| 955 |
this.initialClickPos = null;
|
| 956 |
this.clickStartTime = 0;
|
|
|
|
| 957 |
|
| 958 |
// Reset cursor
|
| 959 |
this.canvas.style.cursor = 'crosshair';
|
|
@@ -1076,38 +1099,76 @@
|
|
| 1076 |
}
|
| 1077 |
this.ctx.stroke();
|
| 1078 |
|
| 1079 |
-
// Draw corner points as squares
|
| 1080 |
const handleSize = isSelected ? 10 : 6;
|
| 1081 |
points.forEach((point, index) => {
|
| 1082 |
-
|
| 1083 |
-
|
| 1084 |
-
|
| 1085 |
-
|
| 1086 |
-
point
|
| 1087 |
-
|
| 1088 |
-
|
| 1089 |
-
|
| 1090 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1091 |
|
| 1092 |
-
|
|
|
|
|
|
|
| 1093 |
this.ctx.strokeStyle = '#ffffff';
|
| 1094 |
this.ctx.lineWidth = 2;
|
| 1095 |
-
|
|
|
|
| 1096 |
point.x - handleSize / 2,
|
| 1097 |
point.y - handleSize / 2,
|
| 1098 |
handleSize,
|
| 1099 |
handleSize
|
| 1100 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1101 |
}
|
| 1102 |
});
|
| 1103 |
|
| 1104 |
-
// Draw edge handles for selected polygon (
|
| 1105 |
if (isSelected && points.length > 2 && this.showEdgeHandles) {
|
| 1106 |
this.drawEdgeHandles(points);
|
| 1107 |
}
|
| 1108 |
}
|
| 1109 |
|
| 1110 |
|
|
|
|
| 1111 |
drawEdgeHandles(points) {
|
| 1112 |
this.ctx.fillStyle = 'rgba(0, 102, 255, 0.8)';
|
| 1113 |
this.ctx.strokeStyle = '#ffffff';
|
|
@@ -2065,7 +2126,7 @@
|
|
| 2065 |
// Other key handlers
|
| 2066 |
switch (e.key) {
|
| 2067 |
case 'Delete':
|
| 2068 |
-
case 'Backspace':
|
| 2069 |
e.preventDefault();
|
| 2070 |
this.deleteSelectedBox();
|
| 2071 |
break;
|
|
@@ -2209,6 +2270,7 @@
|
|
| 2209 |
}
|
| 2210 |
|
| 2211 |
// New method to populate polygon points list
|
|
|
|
| 2212 |
populatePolygonPointsList(points) {
|
| 2213 |
const pointsList = document.getElementById('pointsList');
|
| 2214 |
const pointCount = document.getElementById('pointCount');
|
|
@@ -2219,8 +2281,9 @@
|
|
| 2219 |
points.forEach((point, index) => {
|
| 2220 |
const row = document.createElement('div');
|
| 2221 |
row.className = 'point-edit-row';
|
|
|
|
| 2222 |
row.innerHTML = `
|
| 2223 |
-
<span style="font-size:
|
| 2224 |
<input type="number" class="point-edit-input" value="${Math.round(point.x)}"
|
| 2225 |
data-index="${index}" data-coord="x" min="0" max="${this.originalWidth}">
|
| 2226 |
<input type="number" class="point-edit-input" value="${Math.round(point.y)}"
|
|
@@ -2236,13 +2299,89 @@
|
|
| 2236 |
// Add event listeners for point inputs
|
| 2237 |
pointsList.querySelectorAll('.point-edit-input').forEach(input => {
|
| 2238 |
input.addEventListener('change', (e) => this.updatePolygonPoint(e));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2239 |
});
|
| 2240 |
|
| 2241 |
// Add event listeners for delete buttons
|
| 2242 |
pointsList.querySelectorAll('.point-delete-btn').forEach(btn => {
|
| 2243 |
btn.addEventListener('click', (e) => this.deletePolygonPoint(e));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2244 |
});
|
| 2245 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2246 |
|
| 2247 |
// New method to update polygon point
|
| 2248 |
updatePolygonPoint(e) {
|
|
|
|
| 473 |
.point-edit-input {
|
| 474 |
flex: 1;
|
| 475 |
padding: 2px 4px;
|
| 476 |
+
font-size: 15px;
|
| 477 |
border: 1px solid #d1d5db;
|
| 478 |
border-radius: 3px;
|
| 479 |
width: 50px;
|
|
|
|
| 485 |
border: none;
|
| 486 |
border-radius: 3px;
|
| 487 |
padding: 2px 6px;
|
| 488 |
+
font-size: 15px;
|
| 489 |
cursor: pointer;
|
| 490 |
min-width: 20px;
|
| 491 |
}
|
|
|
|
| 493 |
.point-delete-btn:hover {
|
| 494 |
background: #e53e3e;
|
| 495 |
}
|
| 496 |
+
|
| 497 |
+
/* Add to your existing CSS */
|
| 498 |
+
.point-highlighted {
|
| 499 |
+
background: rgba(255, 215, 0, 0.8) !important;
|
| 500 |
+
border: 3px solid #ff6b00 !important;
|
| 501 |
+
box-shadow: 0 0 10px rgba(255, 107, 0, 0.6) !important;
|
| 502 |
+
}
|
| 503 |
+
|
| 504 |
+
.point-edit-row.highlighted {
|
| 505 |
+
background: #fff3cd !important;
|
| 506 |
+
border: 2px solid #ffc107 !important;
|
| 507 |
+
border-radius: 6px !important;
|
| 508 |
+
box-shadow: 0 2px 8px rgba(255, 193, 7, 0.3) !important;
|
| 509 |
+
}
|
| 510 |
+
|
| 511 |
+
.point-edit-input.highlighted {
|
| 512 |
+
border-color: #ffc107 !important;
|
| 513 |
+
background: #fff3cd !important;
|
| 514 |
+
}
|
| 515 |
</style>
|
| 516 |
</head>
|
| 517 |
|
|
|
|
| 786 |
this.clickStartTime = 0;
|
| 787 |
this.modeIndicatorTimeout = null;
|
| 788 |
|
| 789 |
+
// Add this new property for point highlighting
|
| 790 |
+
this.highlightedPointIndex = -1;
|
| 791 |
+
|
| 792 |
this.init();
|
| 793 |
}
|
| 794 |
|
|
|
|
| 976 |
this.waitingForDrag = false;
|
| 977 |
this.initialClickPos = null;
|
| 978 |
this.clickStartTime = 0;
|
| 979 |
+
this.highlightedPointIndex = -1;
|
| 980 |
|
| 981 |
// Reset cursor
|
| 982 |
this.canvas.style.cursor = 'crosshair';
|
|
|
|
| 1099 |
}
|
| 1100 |
this.ctx.stroke();
|
| 1101 |
|
| 1102 |
+
// Draw corner points as squares
|
| 1103 |
const handleSize = isSelected ? 10 : 6;
|
| 1104 |
points.forEach((point, index) => {
|
| 1105 |
+
// Check if this point should be highlighted
|
| 1106 |
+
const isHighlighted = isSelected && this.highlightedPointIndex === index;
|
| 1107 |
+
|
| 1108 |
+
if (isHighlighted) {
|
| 1109 |
+
// Draw highlighted point with special styling
|
| 1110 |
+
this.ctx.fillStyle = '#FFD700'; // Gold color
|
| 1111 |
+
this.ctx.strokeStyle = '#FF6B00'; // Orange border
|
| 1112 |
+
this.ctx.lineWidth = 3;
|
| 1113 |
+
|
| 1114 |
+
// Draw larger, more visible handle
|
| 1115 |
+
const highlightSize = handleSize + 6;
|
| 1116 |
+
this.ctx.fillRect(
|
| 1117 |
+
point.x - highlightSize / 2,
|
| 1118 |
+
point.y - highlightSize / 2,
|
| 1119 |
+
highlightSize,
|
| 1120 |
+
highlightSize
|
| 1121 |
+
);
|
| 1122 |
+
this.ctx.strokeRect(
|
| 1123 |
+
point.x - highlightSize / 2,
|
| 1124 |
+
point.y - highlightSize / 2,
|
| 1125 |
+
highlightSize,
|
| 1126 |
+
highlightSize
|
| 1127 |
+
);
|
| 1128 |
+
|
| 1129 |
+
// Add pulsing glow effect
|
| 1130 |
+
this.ctx.shadowColor = '#FF6B00';
|
| 1131 |
+
this.ctx.shadowBlur = 10;
|
| 1132 |
+
this.ctx.strokeRect(
|
| 1133 |
+
point.x - highlightSize / 2,
|
| 1134 |
+
point.y - highlightSize / 2,
|
| 1135 |
+
highlightSize,
|
| 1136 |
+
highlightSize
|
| 1137 |
+
);
|
| 1138 |
+
this.ctx.shadowBlur = 0; // Reset shadow
|
| 1139 |
|
| 1140 |
+
} else {
|
| 1141 |
+
// Draw normal point
|
| 1142 |
+
this.ctx.fillStyle = isSelected ? '#0066ff' : strokeColor;
|
| 1143 |
this.ctx.strokeStyle = '#ffffff';
|
| 1144 |
this.ctx.lineWidth = 2;
|
| 1145 |
+
|
| 1146 |
+
this.ctx.fillRect(
|
| 1147 |
point.x - handleSize / 2,
|
| 1148 |
point.y - handleSize / 2,
|
| 1149 |
handleSize,
|
| 1150 |
handleSize
|
| 1151 |
);
|
| 1152 |
+
|
| 1153 |
+
if (isSelected) {
|
| 1154 |
+
this.ctx.strokeRect(
|
| 1155 |
+
point.x - handleSize / 2,
|
| 1156 |
+
point.y - handleSize / 2,
|
| 1157 |
+
handleSize,
|
| 1158 |
+
handleSize
|
| 1159 |
+
);
|
| 1160 |
+
}
|
| 1161 |
}
|
| 1162 |
});
|
| 1163 |
|
| 1164 |
+
// Draw edge handles for selected polygon (existing code)
|
| 1165 |
if (isSelected && points.length > 2 && this.showEdgeHandles) {
|
| 1166 |
this.drawEdgeHandles(points);
|
| 1167 |
}
|
| 1168 |
}
|
| 1169 |
|
| 1170 |
|
| 1171 |
+
|
| 1172 |
drawEdgeHandles(points) {
|
| 1173 |
this.ctx.fillStyle = 'rgba(0, 102, 255, 0.8)';
|
| 1174 |
this.ctx.strokeStyle = '#ffffff';
|
|
|
|
| 2126 |
// Other key handlers
|
| 2127 |
switch (e.key) {
|
| 2128 |
case 'Delete':
|
| 2129 |
+
// case 'Backspace':
|
| 2130 |
e.preventDefault();
|
| 2131 |
this.deleteSelectedBox();
|
| 2132 |
break;
|
|
|
|
| 2270 |
}
|
| 2271 |
|
| 2272 |
// New method to populate polygon points list
|
| 2273 |
+
// Enhanced method to populate polygon points list with hover highlighting
|
| 2274 |
populatePolygonPointsList(points) {
|
| 2275 |
const pointsList = document.getElementById('pointsList');
|
| 2276 |
const pointCount = document.getElementById('pointCount');
|
|
|
|
| 2281 |
points.forEach((point, index) => {
|
| 2282 |
const row = document.createElement('div');
|
| 2283 |
row.className = 'point-edit-row';
|
| 2284 |
+
row.setAttribute('data-point-index', index);
|
| 2285 |
row.innerHTML = `
|
| 2286 |
+
<span style="font-size: 15px; color: #4a5568; min-width: 15px;">${index + 1}:</span>
|
| 2287 |
<input type="number" class="point-edit-input" value="${Math.round(point.x)}"
|
| 2288 |
data-index="${index}" data-coord="x" min="0" max="${this.originalWidth}">
|
| 2289 |
<input type="number" class="point-edit-input" value="${Math.round(point.y)}"
|
|
|
|
| 2299 |
// Add event listeners for point inputs
|
| 2300 |
pointsList.querySelectorAll('.point-edit-input').forEach(input => {
|
| 2301 |
input.addEventListener('change', (e) => this.updatePolygonPoint(e));
|
| 2302 |
+
|
| 2303 |
+
// Add hover event listeners for highlighting
|
| 2304 |
+
input.addEventListener('mouseenter', (e) => this.highlightPolygonPoint(e));
|
| 2305 |
+
input.addEventListener('mouseleave', (e) => this.unhighlightPolygonPoint(e));
|
| 2306 |
+
input.addEventListener('focus', (e) => this.highlightPolygonPoint(e));
|
| 2307 |
+
input.addEventListener('blur', (e) => this.unhighlightPolygonPoint(e));
|
| 2308 |
});
|
| 2309 |
|
| 2310 |
// Add event listeners for delete buttons
|
| 2311 |
pointsList.querySelectorAll('.point-delete-btn').forEach(btn => {
|
| 2312 |
btn.addEventListener('click', (e) => this.deletePolygonPoint(e));
|
| 2313 |
+
|
| 2314 |
+
// Add hover event listeners for delete buttons
|
| 2315 |
+
btn.addEventListener('mouseenter', (e) => this.highlightPolygonPoint(e));
|
| 2316 |
+
btn.addEventListener('mouseleave', (e) => this.unhighlightPolygonPoint(e));
|
| 2317 |
+
});
|
| 2318 |
+
|
| 2319 |
+
// Add hover listeners for entire rows
|
| 2320 |
+
pointsList.querySelectorAll('.point-edit-row').forEach(row => {
|
| 2321 |
+
row.addEventListener('mouseenter', (e) => this.highlightPolygonPointByRow(e));
|
| 2322 |
+
row.addEventListener('mouseleave', (e) => this.unhighlightPolygonPointByRow(e));
|
| 2323 |
});
|
| 2324 |
}
|
| 2325 |
+
// Method to highlight a polygon point on canvas
|
| 2326 |
+
highlightPolygonPoint(e) {
|
| 2327 |
+
const index = parseInt(e.target.dataset.index);
|
| 2328 |
+
if (this.selectedBoxIndex >= 0 && index >= 0) {
|
| 2329 |
+
this.highlightedPointIndex = index;
|
| 2330 |
+
|
| 2331 |
+
// Highlight the row in sidebar
|
| 2332 |
+
const row = e.target.closest('.point-edit-row');
|
| 2333 |
+
if (row) {
|
| 2334 |
+
row.classList.add('highlighted');
|
| 2335 |
+
row.querySelectorAll('.point-edit-input').forEach(input => {
|
| 2336 |
+
input.classList.add('highlighted');
|
| 2337 |
+
});
|
| 2338 |
+
}
|
| 2339 |
+
|
| 2340 |
+
this.drawCanvas();
|
| 2341 |
+
}
|
| 2342 |
+
}
|
| 2343 |
+
|
| 2344 |
+
// Method to unhighlight a polygon point
|
| 2345 |
+
unhighlightPolygonPoint(e) {
|
| 2346 |
+
this.highlightedPointIndex = -1;
|
| 2347 |
+
|
| 2348 |
+
// Remove highlight from sidebar row
|
| 2349 |
+
const row = e.target.closest('.point-edit-row');
|
| 2350 |
+
if (row) {
|
| 2351 |
+
row.classList.remove('highlighted');
|
| 2352 |
+
row.querySelectorAll('.point-edit-input').forEach(input => {
|
| 2353 |
+
input.classList.remove('highlighted');
|
| 2354 |
+
});
|
| 2355 |
+
}
|
| 2356 |
+
|
| 2357 |
+
this.drawCanvas();
|
| 2358 |
+
}
|
| 2359 |
+
|
| 2360 |
+
// Method to highlight by hovering over entire row
|
| 2361 |
+
highlightPolygonPointByRow(e) {
|
| 2362 |
+
const row = e.currentTarget;
|
| 2363 |
+
const index = parseInt(row.dataset.pointIndex);
|
| 2364 |
+
if (index >= 0) {
|
| 2365 |
+
this.highlightedPointIndex = index;
|
| 2366 |
+
row.classList.add('highlighted');
|
| 2367 |
+
row.querySelectorAll('.point-edit-input').forEach(input => {
|
| 2368 |
+
input.classList.add('highlighted');
|
| 2369 |
+
});
|
| 2370 |
+
this.drawCanvas();
|
| 2371 |
+
}
|
| 2372 |
+
}
|
| 2373 |
+
|
| 2374 |
+
// Method to unhighlight by leaving row
|
| 2375 |
+
unhighlightPolygonPointByRow(e) {
|
| 2376 |
+
const row = e.currentTarget;
|
| 2377 |
+
this.highlightedPointIndex = -1;
|
| 2378 |
+
row.classList.remove('highlighted');
|
| 2379 |
+
row.querySelectorAll('.point-edit-input').forEach(input => {
|
| 2380 |
+
input.classList.remove('highlighted');
|
| 2381 |
+
});
|
| 2382 |
+
this.drawCanvas();
|
| 2383 |
+
}
|
| 2384 |
+
|
| 2385 |
|
| 2386 |
// New method to update polygon point
|
| 2387 |
updatePolygonPoint(e) {
|