canvas based cropping
All checks were successful
Build Images and Deploy / Update-PROD-Stack (push) Successful in 1m34s

This commit is contained in:
2026-02-09 17:00:37 -05:00
parent 356b10db88
commit 587688e5f8

View File

@@ -125,6 +125,8 @@
.video-preview {
margin: 20px 0;
text-align: center;
position: relative;
display: inline-block;
}
.video-preview video {
@@ -132,6 +134,47 @@
max-height: 400px;
border-radius: 8px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
display: block;
}
.crop-canvas {
position: absolute;
top: 0;
left: 0;
cursor: crosshair;
border-radius: 8px;
display: none;
}
.crop-canvas.active {
display: block;
}
.crop-mode-btn {
margin: 10px 0;
padding: 10px 20px;
background: #28a745;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: 600;
transition: all 0.3s;
}
.crop-mode-btn:hover {
background: #218838;
}
.crop-mode-btn.active {
background: #dc3545;
}
.crop-hint {
color: #28a745;
font-size: 0.9em;
margin: 5px 0;
font-weight: 600;
}
.video-info {
@@ -312,7 +355,10 @@
<div class="video-preview">
<video id="video-preview" controls></video>
<canvas id="crop-canvas" class="crop-canvas"></canvas>
</div>
<button class="crop-mode-btn" id="crop-mode-btn">🎯 Click to Draw Crop Area</button>
<p class="crop-hint" id="crop-hint" style="display: none;">Click and drag on the video to select crop area</p>
<div class="video-info" id="video-info"></div>
@@ -404,12 +450,20 @@
<script>
let currentFileId = null;
let videoInfo = null;
let cropMode = false;
let cropStartX = 0;
let cropStartY = 0;
let cropRect = null;
// Upload area handling
const uploadArea = document.getElementById('upload-area');
const videoInput = document.getElementById('video-input');
const uploadLoader = document.getElementById('upload-loader');
const processLoader = document.getElementById('process-loader');
const cropCanvas = document.getElementById('crop-canvas');
const cropCtx = cropCanvas.getContext('2d');
const cropModeBtn = document.getElementById('crop-mode-btn');
const cropHint = document.getElementById('crop-hint');
uploadArea.addEventListener('click', () => videoInput.click());
@@ -474,6 +528,9 @@
// Set default values
document.getElementById('end-time').value = videoInfo.duration.toFixed(2);
// Setup canvas for cropping
setupCropCanvas();
// Show edit section
document.getElementById('upload-section').classList.add('hidden');
document.getElementById('edit-section').classList.remove('hidden');
@@ -485,6 +542,131 @@
}
}
// Setup crop canvas
function setupCropCanvas() {
const video = document.getElementById('video-preview');
// Wait for video to load metadata
video.addEventListener('loadedmetadata', () => {
resizeCropCanvas();
});
// Resize canvas when window resizes
window.addEventListener('resize', resizeCropCanvas);
}
function resizeCropCanvas() {
const video = document.getElementById('video-preview');
cropCanvas.width = video.offsetWidth;
cropCanvas.height = video.offsetHeight;
}
// Crop mode toggle
cropModeBtn.addEventListener('click', () => {
cropMode = !cropMode;
if (cropMode) {
cropCanvas.classList.add('active');
cropModeBtn.classList.add('active');
cropModeBtn.textContent = '❌ Cancel Crop Selection';
cropHint.style.display = 'block';
document.getElementById('video-preview').pause();
} else {
cropCanvas.classList.remove('active');
cropModeBtn.classList.remove('active');
cropModeBtn.textContent = '🎯 Click to Draw Crop Area';
cropHint.style.display = 'none';
clearCropCanvas();
}
});
// Canvas drawing for crop selection
let isDrawing = false;
let startX, startY;
cropCanvas.addEventListener('mousedown', (e) => {
if (!cropMode) return;
isDrawing = true;
const rect = cropCanvas.getBoundingClientRect();
startX = e.clientX - rect.left;
startY = e.clientY - rect.top;
});
cropCanvas.addEventListener('mousemove', (e) => {
if (!cropMode || !isDrawing) return;
const rect = cropCanvas.getBoundingClientRect();
const currentX = e.clientX - rect.left;
const currentY = e.clientY - rect.top;
drawCropRect(startX, startY, currentX - startX, currentY - startY);
});
cropCanvas.addEventListener('mouseup', (e) => {
if (!cropMode || !isDrawing) return;
isDrawing = false;
const rect = cropCanvas.getBoundingClientRect();
const endX = e.clientX - rect.left;
const endY = e.clientY - rect.top;
const width = Math.abs(endX - startX);
const height = Math.abs(endY - startY);
const x = Math.min(startX, endX);
const y = Math.min(startY, endY);
// Calculate actual video coordinates
const video = document.getElementById('video-preview');
const scaleX = videoInfo.width / video.offsetWidth;
const scaleY = videoInfo.height / video.offsetHeight;
const actualX = Math.round(x * scaleX);
const actualY = Math.round(y * scaleY);
const actualWidth = Math.round(width * scaleX);
const actualHeight = Math.round(height * scaleY);
// Update form fields
document.getElementById('crop-x').value = actualX;
document.getElementById('crop-y').value = actualY;
document.getElementById('crop-width').value = actualWidth;
document.getElementById('crop-height').value = actualHeight;
// Exit crop mode
cropMode = false;
cropModeBtn.classList.remove('active');
cropModeBtn.textContent = '🎯 Click to Draw Crop Area';
cropHint.style.display = 'none';
// Keep the rectangle visible for a moment
setTimeout(() => {
cropCanvas.classList.remove('active');
}, 500);
});
function drawCropRect(x, y, width, height) {
clearCropCanvas();
// Draw semi-transparent overlay
cropCtx.fillStyle = 'rgba(0, 0, 0, 0.5)';
cropCtx.fillRect(0, 0, cropCanvas.width, cropCanvas.height);
// Clear the selected area
cropCtx.clearRect(x, y, width, height);
// Draw border around selection
cropCtx.strokeStyle = '#667eea';
cropCtx.lineWidth = 3;
cropCtx.strokeRect(x, y, width, height);
// Draw dimensions text
cropCtx.fillStyle = '#667eea';
cropCtx.font = 'bold 14px sans-serif';
const text = `${Math.abs(Math.round(width))} × ${Math.abs(Math.round(height))}`;
cropCtx.fillText(text, x + 5, y - 5);
}
function clearCropCanvas() {
cropCtx.clearRect(0, 0, cropCanvas.width, cropCanvas.height);
}
// Resolution presets
document.querySelectorAll('.preset-btn').forEach(btn => {
btn.addEventListener('click', () => {
@@ -576,9 +758,16 @@
currentFileId = null;
videoInfo = null;
cropMode = false;
cropRect = null;
document.getElementById('video-preview').src = '';
videoInput.value = '';
clearCropCanvas();
cropCanvas.classList.remove('active');
cropModeBtn.classList.remove('active');
cropModeBtn.textContent = '🎯 Click to Draw Crop Area';
cropHint.style.display = 'none';
document.getElementById('upload-section').classList.remove('hidden');
document.getElementById('edit-section').classList.add('hidden');