This commit is contained in:
@@ -125,6 +125,8 @@
|
|||||||
.video-preview {
|
.video-preview {
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-preview video {
|
.video-preview video {
|
||||||
@@ -132,6 +134,47 @@
|
|||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
|
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 {
|
.video-info {
|
||||||
@@ -312,7 +355,10 @@
|
|||||||
|
|
||||||
<div class="video-preview">
|
<div class="video-preview">
|
||||||
<video id="video-preview" controls></video>
|
<video id="video-preview" controls></video>
|
||||||
|
<canvas id="crop-canvas" class="crop-canvas"></canvas>
|
||||||
</div>
|
</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>
|
<div class="video-info" id="video-info"></div>
|
||||||
|
|
||||||
@@ -404,12 +450,20 @@
|
|||||||
<script>
|
<script>
|
||||||
let currentFileId = null;
|
let currentFileId = null;
|
||||||
let videoInfo = null;
|
let videoInfo = null;
|
||||||
|
let cropMode = false;
|
||||||
|
let cropStartX = 0;
|
||||||
|
let cropStartY = 0;
|
||||||
|
let cropRect = null;
|
||||||
|
|
||||||
// Upload area handling
|
// Upload area handling
|
||||||
const uploadArea = document.getElementById('upload-area');
|
const uploadArea = document.getElementById('upload-area');
|
||||||
const videoInput = document.getElementById('video-input');
|
const videoInput = document.getElementById('video-input');
|
||||||
const uploadLoader = document.getElementById('upload-loader');
|
const uploadLoader = document.getElementById('upload-loader');
|
||||||
const processLoader = document.getElementById('process-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());
|
uploadArea.addEventListener('click', () => videoInput.click());
|
||||||
|
|
||||||
@@ -474,6 +528,9 @@
|
|||||||
// Set default values
|
// Set default values
|
||||||
document.getElementById('end-time').value = videoInfo.duration.toFixed(2);
|
document.getElementById('end-time').value = videoInfo.duration.toFixed(2);
|
||||||
|
|
||||||
|
// Setup canvas for cropping
|
||||||
|
setupCropCanvas();
|
||||||
|
|
||||||
// Show edit section
|
// Show edit section
|
||||||
document.getElementById('upload-section').classList.add('hidden');
|
document.getElementById('upload-section').classList.add('hidden');
|
||||||
document.getElementById('edit-section').classList.remove('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
|
// Resolution presets
|
||||||
document.querySelectorAll('.preset-btn').forEach(btn => {
|
document.querySelectorAll('.preset-btn').forEach(btn => {
|
||||||
btn.addEventListener('click', () => {
|
btn.addEventListener('click', () => {
|
||||||
@@ -576,9 +758,16 @@
|
|||||||
|
|
||||||
currentFileId = null;
|
currentFileId = null;
|
||||||
videoInfo = null;
|
videoInfo = null;
|
||||||
|
cropMode = false;
|
||||||
|
cropRect = null;
|
||||||
|
|
||||||
document.getElementById('video-preview').src = '';
|
document.getElementById('video-preview').src = '';
|
||||||
videoInput.value = '';
|
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('upload-section').classList.remove('hidden');
|
||||||
document.getElementById('edit-section').classList.add('hidden');
|
document.getElementById('edit-section').classList.add('hidden');
|
||||||
|
|||||||
Reference in New Issue
Block a user