fix: canvas fits image exactly, chained annotation loading, arrow move tracking

- Canvas now sizes to match the scaled image dimensions (zero empty space)
  instead of using a fixed aspect ratio, fixing coordinate mismatch between
  editor and viewer
- Annotations load only after background image is ready via _pendingAnnotations
  pattern, preventing placement at wrong coordinates
- Arrow endpoints (arrowX1/Y1/X2/Y2) update on object:modified using
  transform delta, so moved arrows serialize at correct position
- Coordinate scaling on load: coordScale = currentImageScale / savedImageScale
  handles annotations saved at different screen widths

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Adriano
2026-02-08 16:10:21 +01:00
parent f2df6be060
commit 9e1bb20b36
6 changed files with 336 additions and 85 deletions
+31 -1
View File
@@ -1075,7 +1075,14 @@
{% block extra_js %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
<script>if(typeof pdfjsLib!=='undefined')pdfjsLib.GlobalWorkerOptions.workerSrc='https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';</script>
<script src="{{ url_for('static', filename='js/annotation-viewer.js') }}?v=4"></script>
<script src="{{ url_for('static', filename='js/annotation-viewer.js') }}?v=6"></script>
<script>
// Force reload when page is restored from browser bfcache (back/forward navigation).
// This ensures fresh data is displayed after editing annotations in task_drawing.
window.addEventListener('pageshow', function (event) {
if (event.persisted) { window.location.reload(); }
});
</script>
<script>
function taskEditor() {
return {
@@ -1126,6 +1133,29 @@ function taskEditor() {
// Sort tasks by order_index on load
this.tasks.sort((a, b) => (a.order_index || 0) - (b.order_index || 0));
// Check if returning from task_drawing with updated annotations
try {
var updatedRaw = sessionStorage.getItem('taskDrawingUpdated');
if (updatedRaw) {
sessionStorage.removeItem('taskDrawingUpdated');
var updated = JSON.parse(updatedRaw);
if (updated.taskId) {
var task = this.tasks.find(function(t) { return t.id === updated.taskId; });
if (task) {
// Merge updated annotations into local state
if (updated.annotations_json) {
task.annotations_json = (typeof updated.annotations_json === 'string')
? JSON.parse(updated.annotations_json) : updated.annotations_json;
}
// Auto-expand the edited task and render preview
this.expandedTask = task.id;
this.renderTaskPreview(task);
return; // skip default expansion logic
}
}
}
} catch (_e) { /* sessionStorage parse error - ignore */ }
// Auto-expand the first task if there is only one
if (this.tasks.length === 1) {
this.expandedTask = this.tasks[0].id;