Spaces:
Running
Running
File size: 10,855 Bytes
43a8c52 ec4dbff 43a8c52 ec4dbff 43a8c52 ec4dbff 43a8c52 59dcb0c 43a8c52 ec4dbff 59dcb0c bb6a6e7 43a8c52 59dcb0c ec4dbff 43a8c52 ec4dbff 43a8c52 59dcb0c 43a8c52 ec4dbff 43a8c52 ec4dbff 43a8c52 59dcb0c 5dbb1e4 43a8c52 ec4dbff 76b0907 ec4dbff ca1437b 00280b6 ec4dbff 43a8c52 ec4dbff 00280b6 ca1437b 76b0907 ec4dbff 76b0907 ec4dbff ca1437b ec4dbff ca1437b ec4dbff f4172cc ca1437b ec4dbff ca1437b ec4dbff ca1437b ec4dbff ca1437b ec4dbff ca1437b ec4dbff ca1437b ec4dbff ca1437b ec4dbff 9511f1a 43a8c52 ec4dbff 43a8c52 ca1437b 43a8c52 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
document.addEventListener('DOMContentLoaded', function() {
// DOM Elements
const dropZone = document.getElementById('dropZone');
const imageUpload = document.getElementById('imageUpload');
const uploadBtn = document.getElementById('uploadBtn');
const generateBtn = document.getElementById('generateBtn');
const previewContainer = document.getElementById('previewContainer');
const resultsSection = document.getElementById('resultsSection');
const posterPages = document.getElementById('posterPages');
const printAllBtn = document.getElementById('printAllBtn');
const downloadAllBtn = document.getElementById('downloadAllBtn');
const resetBtn = document.getElementById('resetBtn');
const pageCount = document.getElementById('pageCount');
const orientation = document.getElementById('orientation');
const overlapX = document.getElementById('overlapX');
const overlapY = document.getElementById('overlapY');
const showGrid = document.getElementById('showGrid');
const centerOverlap = document.getElementById('centerOverlap');
let uploadedImage = null;
// Event Listeners
uploadBtn.addEventListener('click', () => imageUpload.click());
imageUpload.addEventListener('change', handleImageUpload);
dropZone.addEventListener('dragover', handleDragOver);
dropZone.addEventListener('dragleave', handleDragLeave);
dropZone.addEventListener('drop', handleDrop);
generateBtn.addEventListener('click', generatePosterPages);
printAllBtn.addEventListener('click', printAllPages);
downloadAllBtn.addEventListener('click', downloadAllPages);
resetBtn.addEventListener('click', resetApp);
// Functions
function handleImageUpload(e) {
const file = e.target.files[0];
if (file && file.type.match('image.*')) {
processImageFile(file);
}
}
function handleDragOver(e) {
e.preventDefault();
e.stopPropagation();
dropZone.classList.add('drag-over');
}
function handleDragLeave(e) {
e.preventDefault();
e.stopPropagation();
dropZone.classList.remove('drag-over');
}
function handleDrop(e) {
e.preventDefault();
e.stopPropagation();
dropZone.classList.remove('drag-over');
const file = e.dataTransfer.files[0];
if (file && file.type.match('image.*')) {
processImageFile(file);
}
}
function processImageFile(file) {
const reader = new FileReader();
reader.onload = function(e) {
uploadedImage = new Image();
uploadedImage.onload = function() {
displayPreview(uploadedImage);
generateBtn.disabled = false;
};
uploadedImage.src = e.target.result;
};
reader.readAsDataURL(file);
}
function displayPreview(image) {
previewContainer.innerHTML = '';
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const maxWidth = 400;
const maxHeight = 300;
let width = image.width;
let height = image.height;
if (width > maxWidth) {
height = (maxWidth / width) * height;
width = maxWidth;
}
if (height > maxHeight) {
width = (maxHeight / height) * width;
height = maxHeight;
}
canvas.width = width;
canvas.height = height;
ctx.drawImage(image, 0, 0, width, height);
previewContainer.appendChild(canvas);
}
function generatePosterPages() {
if (!uploadedImage) return;
posterPages.innerHTML = '';
resultsSection.classList.remove('hidden');
const pages = parseInt(pageCount.value);
const gridSize = Math.sqrt(pages);
const orient = orientation.value;
const overlapXPx = (parseInt(overlapX.value) / 25.4) * 96; // Convert mm to pixels (96dpi)
const overlapYPx = (parseInt(overlapY.value) / 25.4) * 96; // Convert mm to pixels (96dpi)
const showGuides = showGrid.checked;
const centerOverlaps = centerOverlap.checked;
// Calculate the size of each segment including overlaps
const totalOverlapXPx = overlapXPx * (gridSize - 1);
const totalOverlapYPx = overlapYPx * (gridSize - 1);
// Original image dimensions minus total overlaps
const baseWidth = uploadedImage.width - totalOverlapXPx;
const baseHeight = uploadedImage.height - totalOverlapYPx;
const segmentWidth = baseWidth / gridSize;
const segmentHeight = baseHeight / gridSize;
// Create a canvas for each page
for (let row = 0; row < gridSize; row++) {
for (let col = 0; col < gridSize; col++) {
const pageNumber = row * gridSize + col + 1;
const pageDiv = document.createElement('div');
pageDiv.className = 'poster-page relative';
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Set canvas dimensions based on orientation
if (orient === 'landscape') {
canvas.width = 842; // A4 height as width (landscape)
canvas.height = 595; // A4 width as height (landscape)
} else {
canvas.width = 595; // A4 width in pixels at 72dpi
canvas.height = 842; // A4 height in pixels at 72dpi
}
// Calculate source rectangle with overlaps
let sx = col * (segmentWidth) + (col * overlapXPx);
let sy = row * (segmentHeight) + (row * overlapYPx);
let sw = segmentWidth + (col < gridSize-1 ? overlapXPx : 0);
let sh = segmentHeight + (row < gridSize-1 ? overlapYPx : 0);
// Ensure we don't exceed image bounds
sx = Math.max(0, Math.min(sx, uploadedImage.width - sw));
sy = Math.max(0, Math.min(sy, uploadedImage.height - sh));
sw = Math.min(sw, uploadedImage.width - sx);
sh = Math.min(sh, uploadedImage.height - sy);
// Draw the image segment
ctx.save();
if (orient === 'diagonal') {
// Diagonal orientation
ctx.translate(canvas.width/2, canvas.height/2);
ctx.rotate(Math.PI/4);
ctx.drawImage(
uploadedImage,
sx, sy, sw, sh,
-canvas.width/2, -canvas.height/2, canvas.width, canvas.height
);
} else {
// Standard orientation (portrait or landscape)
// Maintain aspect ratio while filling canvas
const imgRatio = sw / sh;
const canvasRatio = canvas.width / canvas.height;
let drawWidth, drawHeight, offsetX = 0, offsetY = 0;
if (imgRatio > canvasRatio) {
// Image is wider than canvas - fill width
drawWidth = canvas.width;
drawHeight = canvas.width / imgRatio;
offsetY = (canvas.height - drawHeight) / 2;
} else {
// Image is taller than canvas - fill height
drawHeight = canvas.height;
drawWidth = canvas.height * imgRatio;
offsetX = (canvas.width - drawWidth) / 2;
}
ctx.drawImage(
uploadedImage,
sx, sy, sw, sh,
offsetX, offsetY, drawWidth, drawHeight
);
}
// Draw cutting guides if enabled
if (showGuides) {
ctx.strokeStyle = 'rgba(255, 0, 0, 0.7)';
ctx.lineWidth = 2;
if (orient === 'portrait' || orient === 'landscape') {
// Draw border for overlap areas
const borderX = 10;
const borderY = 10;
const borderWidth = canvas.width - 20;
const borderHeight = canvas.height - 20;
ctx.strokeRect(borderX, borderY, borderWidth, borderHeight);
// Draw center marks
ctx.beginPath();
ctx.moveTo(canvas.width/2 - 15, canvas.height/2);
ctx.lineTo(canvas.width/2 + 15, canvas.height/2);
ctx.moveTo(canvas.width/2, canvas.height/2 - 15);
ctx.lineTo(canvas.width/2, canvas.height/2 + 15);
ctx.stroke();
}
}
// Draw border around the entire canvas
ctx.strokeStyle = 'rgba(0, 0, 0, 0.5)';
ctx.lineWidth = 2;
ctx.strokeRect(0, 0, canvas.width, canvas.height);
ctx.restore();
// Add page number
const pageNumDiv = document.createElement('div');
pageNumDiv.className = 'absolute top-2 right-2 bg-white bg-opacity-80 px-2 py-1 rounded text-sm font-bold';
pageNumDiv.textContent = pageNumber;
pageDiv.appendChild(pageNumDiv);
// Add canvas to page
pageDiv.appendChild(canvas);
posterPages.appendChild(pageDiv);
}
}
// Scroll to results
resultsSection.scrollIntoView({ behavior: 'smooth' });
}
function printAllPages() {
window.print();
}
function downloadAllPages() {
alert('PDF generation would be implemented here with a library like jsPDF or browser print to PDF');
}
function resetApp() {
uploadedImage = null;
previewContainer.innerHTML = `
<i data-feather="image" class="w-16 h-16 mx-auto text-gray-400 mb-3"></i>
<p class="text-gray-600">Your image preview will appear here</p>
`;
feather.replace();
posterPages.innerHTML = '';
resultsSection.classList.add('hidden');
generateBtn.disabled = true;
imageUpload.value = '';
}
}); |