posterpuzzle-maker / script.js
hbf0421's picture
همه صفحات ساخته شده رو در یک فایل pdf بتوان پرینت گرفت
bf04b1a verified
document.addEventListener('DOMContentLoaded', function() {
// DOM elements
const fileInput = document.getElementById('file-input');
const uploadBtn = document.getElementById('upload-btn');
const dropZone = document.getElementById('drop-zone');
const imagePreview = document.getElementById('image-preview');
const imagePreviewContainer = document.getElementById('image-preview-container');
const emptyState = document.getElementById('empty-state');
const pageCountInput = document.getElementById('page-count');
const pageCountValue = document.getElementById('page-count-value');
const portraitBtn = document.getElementById('portrait');
const landscapeBtn = document.getElementById('landscape');
const previewControls = document.getElementById('preview-controls');
const generateBtn = document.getElementById('generate-btn');
const resultSection = document.getElementById('result-section');
const posterPages = document.getElementById('poster-pages');
const downloadAllBtn = document.getElementById('download-all');
const printAllBtn = document.getElementById('print-all');
// Current image and settings
let currentImage = null;
let currentOrientation = 'portrait';
let currentPageCount = 4;
// Event listeners
uploadBtn.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', handleFileSelect);
dropZone.addEventListener('dragover', handleDragOver);
dropZone.addEventListener('dragleave', handleDragLeave);
dropZone.addEventListener('drop', handleDrop);
pageCountInput.addEventListener('input', updatePageCount);
portraitBtn.addEventListener('click', () => setOrientation('portrait'));
landscapeBtn.addEventListener('click', () => setOrientation('landscape'));
generateBtn.addEventListener('click', generatePosterPages);
downloadAllBtn.addEventListener('click', downloadAllPages);
printAllBtn.addEventListener('click', printAllPages);
document.getElementById('pdf-btn').addEventListener('click', generatePDF);
// Update page count display
function updatePageCount() {
currentPageCount = parseInt(pageCountInput.value);
pageCountValue.textContent = currentPageCount;
}
// Set orientation
function setOrientation(orientation) {
currentOrientation = orientation;
if (orientation === 'portrait') {
portraitBtn.classList.add('active', 'bg-indigo-100', 'text-indigo-700');
portraitBtn.classList.remove('border', 'border-gray-300');
landscapeBtn.classList.remove('active', 'bg-indigo-100', 'text-indigo-700');
landscapeBtn.classList.add('border', 'border-gray-300');
} else {
landscapeBtn.classList.add('active', 'bg-indigo-100', 'text-indigo-700');
landscapeBtn.classList.remove('border', 'border-gray-300');
portraitBtn.classList.remove('active', 'bg-indigo-100', 'text-indigo-700');
portraitBtn.classList.add('border', 'border-gray-300');
}
}
// Handle file selection
function handleFileSelect(e) {
const file = e.target.files[0];
if (file && file.type.match('image.*')) {
processImageFile(file);
}
}
// Handle drag over
function handleDragOver(e) {
e.preventDefault();
e.stopPropagation();
dropZone.classList.add('highlight');
}
// Handle drag leave
function handleDragLeave(e) {
e.preventDefault();
e.stopPropagation();
dropZone.classList.remove('highlight');
}
// Handle drop
function handleDrop(e) {
e.preventDefault();
e.stopPropagation();
dropZone.classList.remove('highlight');
const file = e.dataTransfer.files[0];
if (file && file.type.match('image.*')) {
processImageFile(file);
}
}
// Process image file
function processImageFile(file) {
const reader = new FileReader();
reader.onload = function(e) {
currentImage = new Image();
currentImage.onload = function() {
showPreview();
};
currentImage.src = e.target.result;
};
reader.readAsDataURL(file);
}
// Show preview
function showPreview() {
imagePreview.src = currentImage.src;
imagePreviewContainer.classList.remove('hidden');
emptyState.classList.add('hidden');
previewControls.classList.remove('hidden');
}
// Generate poster pages
function generatePosterPages() {
if (!currentImage) return;
// Clear previous results
posterPages.innerHTML = '';
resultSection.classList.remove('hidden');
// Calculate dimensions for each page
const aspectRatio = currentImage.width / currentImage.height;
let cols, rows;
if (currentOrientation === 'portrait') {
// For portrait orientation, we'll split vertically first
cols = Math.ceil(Math.sqrt(currentPageCount * (210 / 297))); // A4 ratio
rows = Math.ceil(currentPageCount / cols);
} else {
// For landscape orientation, we'll split horizontally first
rows = Math.ceil(Math.sqrt(currentPageCount * (297 / 210))); // A4 ratio
cols = Math.ceil(currentPageCount / rows);
}
// Create canvas for the entire image
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Size canvas to maintain aspect ratio
if (currentOrientation === 'portrait') {
canvas.width = cols * 210; // A4 width in mm (approximate)
canvas.height = (canvas.width / aspectRatio);
// If height is less than needed for rows, adjust
const neededHeight = rows * 297;
if (canvas.height < neededHeight) {
canvas.height = neededHeight;
canvas.width = canvas.height * aspectRatio;
}
} else {
canvas.height = rows * 210; // A4 height in mm (approximate)
canvas.width = canvas.height * aspectRatio;
// If width is less than needed for cols, adjust
const neededWidth = cols * 297;
if (canvas.width < neededWidth) {
canvas.width = neededWidth;
canvas.height = canvas.width / aspectRatio;
}
}
// Draw the image on canvas
ctx.drawImage(currentImage, 0, 0, canvas.width, canvas.height);
// Calculate each page's dimensions
const pageWidth = canvas.width / cols;
const pageHeight = canvas.height / rows;
// Create individual pages
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
const pageIndex = row * cols + col;
if (pageIndex >= currentPageCount) break;
// Create page canvas
const pageCanvas = document.createElement('canvas');
pageCanvas.width = 2480; // A4 at 300dpi
pageCanvas.height = 3508;
const pageCtx = pageCanvas.getContext('2d');
// Calculate source dimensions
const sx = col * pageWidth;
const sy = row * pageHeight;
const sw = pageWidth;
const sh = pageHeight;
// Draw the portion of the image on the page
pageCtx.drawImage(
canvas,
sx, sy, sw, sh,
0, 0, pageCanvas.width, pageCanvas.height
);
// Add cut lines and page number
addPageMarkings(pageCtx, pageCanvas.width, pageCanvas.height, pageIndex + 1);
// Create page element
const pageElement = document.createElement('div');
pageElement.className = 'poster-page relative';
// Create download button
const downloadBtn = document.createElement('button');
downloadBtn.className = 'absolute top-2 left-2 bg-white bg-opacity-90 p-2 rounded-full shadow hover:bg-opacity-100 transition';
downloadBtn.innerHTML = '<i data-feather="download" class="w-4 h-4"></i>';
downloadBtn.onclick = () => downloadPage(pageCanvas, pageIndex + 1);
// Add image and button to page
const img = document.createElement('img');
img.src = pageCanvas.toDataURL('image/jpeg', 0.9);
img.className = 'w-full h-auto';
pageElement.appendChild(img);
pageElement.appendChild(downloadBtn);
posterPages.appendChild(pageElement);
}
}
feather.replace();
}
// Add page markings (cut lines and page numbers)
function addPageMarkings(ctx, width, height, pageNumber) {
// Cut lines (5mm from edges)
const cutMargin = 59; // 5mm at 300dpi (5/25.4*300)
ctx.strokeStyle = 'rgba(255, 0, 0, 0.5)';
ctx.lineWidth = 2;
ctx.setLineDash([5, 5]);
// Top and bottom lines
ctx.beginPath();
ctx.moveTo(cutMargin, cutMargin);
ctx.lineTo(width - cutMargin, cutMargin);
ctx.moveTo(cutMargin, height - cutMargin);
ctx.lineTo(width - cutMargin, height - cutMargin);
ctx.stroke();
// Left and right lines
ctx.beginPath();
ctx.moveTo(cutMargin, cutMargin);
ctx.lineTo(cutMargin, height - cutMargin);
ctx.moveTo(width - cutMargin, cutMargin);
ctx.lineTo(width - cutMargin, height - cutMargin);
ctx.stroke();
// Page number
ctx.font = 'bold 40px Arial';
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.textAlign = 'right';
ctx.textBaseline = 'bottom';
ctx.fillText(pageNumber.toString(), width - 20, height - 20);
}
// Download a single page
function downloadPage(canvas, pageNumber) {
const link = document.createElement('a');
link.download = `poster-page-${pageNumber}.jpg`;
link.href = canvas.toDataURL('image/jpeg', 0.9);
link.click();
}
// Download all pages
function downloadAllPages() {
const pages = posterPages.querySelectorAll('.poster-page img');
pages.forEach((img, index) => {
const link = document.createElement('a');
link.download = `poster-page-${index + 1}.jpg`;
link.href = img.src;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
}
// Generate PDF of all pages
function generatePDF() {
if (posterPages.children.length === 0) return;
// Include jsPDF library dynamically
const script = document.createElement('script');
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js';
script.onload = function() {
const { jsPDF } = window.jspdf;
const pdf = new jsPDF({
orientation: currentOrientation,
unit: 'mm',
format: 'a4'
});
const pages = posterPages.querySelectorAll('.poster-page img');
const promises = [];
// Convert all images to Image objects to get dimensions
pages.forEach((img, index) => {
const promise = new Promise((resolve) => {
const tempImg = new Image();
tempImg.onload = function() {
resolve({
src: img.src,
width: tempImg.width,
height: tempImg.height,
index: index + 1
});
};
tempImg.src = img.src;
});
promises.push(promise);
});
Promise.all(promises).then((images) => {
images.forEach((img, i) => {
if (i > 0) {
pdf.addPage('a4', currentOrientation);
}
// Calculate dimensions to fit A4 page (210x297mm or 297x210mm)
const pageWidth = currentOrientation === 'portrait' ? 210 : 297;
const pageHeight = currentOrientation === 'portrait' ? 297 : 210;
// Maintain aspect ratio
const imgAspect = img.width / img.height;
const pageAspect = pageWidth / pageHeight;
let width, height;
if (imgAspect > pageAspect) {
width = pageWidth;
height = width / imgAspect;
} else {
height = pageHeight;
width = height * imgAspect;
}
// Center the image
const x = (pageWidth - width) / 2;
const y = (pageHeight - height) / 2;
pdf.addImage(img.src, 'JPEG', x, y, width, height);
// Add page number
pdf.setFontSize(12);
pdf.setTextColor(150);
pdf.text(
`Page ${img.index}`,
currentOrientation === 'portrait' ? 200 : 287,
currentOrientation === 'portrait' ? 290 : 200,
{ align: 'right' }
);
});
pdf.save('poster-pages.pdf');
});
};
document.head.appendChild(script);
}
// Print all pages
function printAllPages() {
if (posterPages.children.length === 0) return;
// Create a print stylesheet
const printStyle = document.createElement('style');
printStyle.innerHTML = `
@media print {
body * {
visibility: hidden;
}
.print-container, .print-container * {
visibility: visible;
}
.print-container {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
page-break-after: always;
}
.print-page {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.print-page img {
max-width: 100%;
max-height: 100%;
}
}
`;
// Create a print container
const printContainer = document.createElement('div');
printContainer.className = 'print-container';
// Clone all pages into print container
const pages = posterPages.querySelectorAll('.poster-page');
pages.forEach(page => {
const clone = page.cloneNode(true);
const pageDiv = document.createElement('div');
pageDiv.className = 'print-page';
pageDiv.appendChild(clone);
printContainer.appendChild(pageDiv);
});
// Create print window
const printWindow = window.open('', '', 'width=800,height=600');
printWindow.document.body.appendChild(printStyle);
printWindow.document.body.appendChild(printContainer);
printWindow.document.close();
// Trigger print after content loads
printWindow.onload = function() {
printWindow.print();
};
}
});