From d94b2d6ab89f8a4a14bbca4bc9bfe2ec354c74fc Mon Sep 17 00:00:00 2001 From: Mike Johnston Date: Mon, 9 Feb 2026 22:35:55 -0500 Subject: [PATCH] improved crop features --- templates/index.html | 66 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/templates/index.html b/templates/index.html index f7a286e..3def55c 100644 --- a/templates/index.html +++ b/templates/index.html @@ -543,6 +543,9 @@
+

+ 💡 Draw crop area on video above • Double-click corner handles to snap to edges +

@@ -752,6 +755,12 @@ scalePercentage = 100; scaleSlider.value = 100; updateScaleDisplay(); + + // Set max values for crop inputs + document.getElementById('crop-x').max = videoInfo.width; + document.getElementById('crop-y').max = videoInfo.height; + document.getElementById('crop-width').max = videoInfo.width; + document.getElementById('crop-height').max = videoInfo.height; // Setup canvas for cropping setupCropCanvas(); @@ -906,10 +915,40 @@ isDraggingHandle = false; isDraggingBox = false; activeHandle = null; + cropCanvas.style.cursor = 'crosshair'; // Keep crop mode active and canvas visible drawCropRect(); }); + + // Handle mouse leaving canvas while dragging + cropCanvas.addEventListener('mouseleave', (e) => { + if (isDrawing || isDraggingHandle || isDraggingBox) { + // Finish the drag operation + updateFormFields(); + isDrawing = false; + isDraggingHandle = false; + isDraggingBox = false; + activeHandle = null; + drawCropRect(); + } + }); + + // Double-click on handles to snap to edges + cropCanvas.addEventListener('dblclick', (e) => { + if (!cropMode || !cropRect) return; + + const rect = cropCanvas.getBoundingClientRect(); + const mouseX = e.clientX - rect.left; + const mouseY = e.clientY - rect.top; + + const handle = getHandleAtPosition(mouseX, mouseY); + if (handle) { + snapHandleToEdge(handle); + updateFormFields(); + drawCropRect(); + } + }); function drawCropRect() { clearCropCanvas(); @@ -1056,6 +1095,33 @@ drawCropRect(); } + function snapHandleToEdge(handle) { + if (!cropRect) return; + + switch (handle) { + case 'tl': // Top-left -> snap to top-left corner + cropRect.width += cropRect.x; // Extend width by current x + cropRect.height += cropRect.y; // Extend height by current y + cropRect.x = 0; + cropRect.y = 0; + break; + case 'tr': // Top-right -> snap to top-right corner + cropRect.width = cropCanvas.width - cropRect.x; + cropRect.height += cropRect.y; + cropRect.y = 0; + break; + case 'bl': // Bottom-left -> snap to bottom-left corner + cropRect.width += cropRect.x; + cropRect.height = cropCanvas.height - cropRect.y; + cropRect.x = 0; + break; + case 'br': // Bottom-right -> snap to bottom-right corner + cropRect.width = cropCanvas.width - cropRect.x; + cropRect.height = cropCanvas.height - cropRect.y; + break; + } + } + function updateFormFields() { if (!cropRect) return;