hbf0421 commited on
Commit
e34a698
·
verified ·
1 Parent(s): 4a5eddd

برای صفحات یک مقدار همپوشانی قابل تغییر قرار بده و در پایان به صورت pdf بتوان همه عکس ها را پرینت کرد

Browse files
Files changed (3) hide show
  1. index.html +21 -8
  2. script.js +63 -17
  3. style.css +4 -1
index.html CHANGED
@@ -35,7 +35,6 @@
35
  </button>
36
  </div>
37
  </div>
38
-
39
  <div class="mt-6">
40
  <label for="page-count" class="block text-sm font-medium text-gray-700 mb-2">Number of A4 Pages</label>
41
  <div class="flex items-center gap-4">
@@ -45,6 +44,13 @@
45
  </div>
46
 
47
  <div class="mt-6">
 
 
 
 
 
 
 
48
  <label for="orientation" class="block text-sm font-medium text-gray-700 mb-2">Orientation</label>
49
  <div class="flex gap-4">
50
  <button id="portrait" class="orientation-btn active bg-indigo-100 text-indigo-700 px-4 py-2 rounded-lg">
@@ -80,11 +86,17 @@
80
  <div id="result-section" class="hidden">
81
  <div class="flex justify-between items-center mb-4">
82
  <h2 class="text-2xl font-bold text-gray-800">Your Poster Pages</h2>
83
- <button id="download-all" class="flex items-center gap-2 bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 transition">
84
- <i data-feather="download"></i>
85
- Download All
86
- </button>
87
- </div>
 
 
 
 
 
 
88
 
89
  <div id="poster-pages" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
90
  <!-- Generated pages will appear here -->
@@ -108,10 +120,11 @@
108
  </main>
109
 
110
  <custom-footer></custom-footer>
111
-
112
  <script src="script.js"></script>
113
  <script>
114
- feather.replace();
 
 
115
  </script>
116
  <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
117
  </body>
 
35
  </button>
36
  </div>
37
  </div>
 
38
  <div class="mt-6">
39
  <label for="page-count" class="block text-sm font-medium text-gray-700 mb-2">Number of A4 Pages</label>
40
  <div class="flex items-center gap-4">
 
44
  </div>
45
 
46
  <div class="mt-6">
47
+ <label for="overlap" class="block text-sm font-medium text-gray-700 mb-2">Overlap between pages (mm)</label>
48
+ <div class="flex items-center gap-4">
49
+ <input type="range" id="overlap" min="0" max="20" value="5" class="w-full">
50
+ <span id="overlap-value" class="font-medium text-gray-800">5mm</span>
51
+ </div>
52
+ </div>
53
+ <div class="mt-6">
54
  <label for="orientation" class="block text-sm font-medium text-gray-700 mb-2">Orientation</label>
55
  <div class="flex gap-4">
56
  <button id="portrait" class="orientation-btn active bg-indigo-100 text-indigo-700 px-4 py-2 rounded-lg">
 
86
  <div id="result-section" class="hidden">
87
  <div class="flex justify-between items-center mb-4">
88
  <h2 class="text-2xl font-bold text-gray-800">Your Poster Pages</h2>
89
+ <div class="flex gap-2">
90
+ <button id="download-all" class="flex items-center gap-2 bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 transition">
91
+ <i data-feather="download"></i>
92
+ Download All
93
+ </button>
94
+ <button id="download-pdf" class="flex items-center gap-2 bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition">
95
+ <i data-feather="file-text"></i>
96
+ PDF for Print
97
+ </button>
98
+ </div>
99
+ </div>
100
 
101
  <div id="poster-pages" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
102
  <!-- Generated pages will appear here -->
 
120
  </main>
121
 
122
  <custom-footer></custom-footer>
 
123
  <script src="script.js"></script>
124
  <script>
125
+ document.addEventListener('jspdfLoaded', function() {
126
+ feather.replace();
127
+ });
128
  </script>
129
  <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
130
  </body>
script.js CHANGED
@@ -1,5 +1,15 @@
 
 
 
 
 
 
 
 
 
 
1
  document.addEventListener('DOMContentLoaded', function() {
2
- // DOM elements
3
  const fileInput = document.getElementById('file-input');
4
  const uploadBtn = document.getElementById('upload-btn');
5
  const dropZone = document.getElementById('drop-zone');
@@ -15,33 +25,44 @@ document.addEventListener('DOMContentLoaded', function() {
15
  const resultSection = document.getElementById('result-section');
16
  const posterPages = document.getElementById('poster-pages');
17
  const downloadAllBtn = document.getElementById('download-all');
 
 
 
18
 
19
  // Current image and settings
20
- let currentImage = null;
21
  let currentOrientation = 'portrait';
22
  let currentPageCount = 4;
23
-
24
- // Event listeners
25
  uploadBtn.addEventListener('click', () => fileInput.click());
26
  fileInput.addEventListener('change', handleFileSelect);
27
  dropZone.addEventListener('dragover', handleDragOver);
28
  dropZone.addEventListener('dragleave', handleDragLeave);
29
  dropZone.addEventListener('drop', handleDrop);
30
  pageCountInput.addEventListener('input', updatePageCount);
31
- portraitBtn.addEventListener('click', () => setOrientation('portrait'));
 
32
  landscapeBtn.addEventListener('click', () => setOrientation('landscape'));
33
  generateBtn.addEventListener('click', generatePosterPages);
34
  downloadAllBtn.addEventListener('click', downloadAllPages);
 
35
 
36
  // Update page count display
37
- function updatePageCount() {
38
  currentPageCount = parseInt(pageCountInput.value);
39
  pageCountValue.textContent = currentPageCount;
40
  }
41
 
42
  // Set orientation
 
 
 
 
 
 
43
  function setOrientation(orientation) {
44
- currentOrientation = orientation;
45
  if (orientation === 'portrait') {
46
  portraitBtn.classList.add('active', 'bg-indigo-100', 'text-indigo-700');
47
  portraitBtn.classList.remove('border', 'border-gray-300');
@@ -161,12 +182,11 @@ document.addEventListener('DOMContentLoaded', function() {
161
 
162
  // Draw the image on canvas
163
  ctx.drawImage(currentImage, 0, 0, canvas.width, canvas.height);
164
-
165
- // Calculate each page's dimensions
166
- const pageWidth = canvas.width / cols;
167
- const pageHeight = canvas.height / rows;
168
-
169
- // Create individual pages
170
  for (let row = 0; row < rows; row++) {
171
  for (let col = 0; col < cols; col++) {
172
  const pageIndex = row * cols + col;
@@ -179,12 +199,11 @@ document.addEventListener('DOMContentLoaded', function() {
179
  const pageCtx = pageCanvas.getContext('2d');
180
 
181
  // Calculate source dimensions
182
- const sx = col * pageWidth;
183
- const sy = row * pageHeight;
184
  const sw = pageWidth;
185
  const sh = pageHeight;
186
-
187
- // Draw the portion of the image on the page
188
  pageCtx.drawImage(
189
  canvas,
190
  sx, sy, sw, sh,
@@ -271,4 +290,31 @@ document.addEventListener('DOMContentLoaded', function() {
271
  document.body.removeChild(link);
272
  });
273
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  });
 
1
+
2
+ // Load jsPDF library
3
+ const script = document.createElement('script');
4
+ script.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js';
5
+ script.onload = function() {
6
+ window.jspdf = window.jspdf.jsPDF;
7
+ document.dispatchEvent(new Event('jspdfLoaded'));
8
+ };
9
+ document.head.appendChild(script);
10
+
11
  document.addEventListener('DOMContentLoaded', function() {
12
+ // DOM elements
13
  const fileInput = document.getElementById('file-input');
14
  const uploadBtn = document.getElementById('upload-btn');
15
  const dropZone = document.getElementById('drop-zone');
 
25
  const resultSection = document.getElementById('result-section');
26
  const posterPages = document.getElementById('poster-pages');
27
  const downloadAllBtn = document.getElementById('download-all');
28
+ const downloadPdfBtn = document.getElementById('download-pdf');
29
+ const overlapInput = document.getElementById('overlap');
30
+ const overlapValue = document.getElementById('overlap-value');
31
 
32
  // Current image and settings
33
+ let currentImage = null;
34
  let currentOrientation = 'portrait';
35
  let currentPageCount = 4;
36
+ let currentOverlap = 5; // in mm
37
+ // Event listeners
38
  uploadBtn.addEventListener('click', () => fileInput.click());
39
  fileInput.addEventListener('change', handleFileSelect);
40
  dropZone.addEventListener('dragover', handleDragOver);
41
  dropZone.addEventListener('dragleave', handleDragLeave);
42
  dropZone.addEventListener('drop', handleDrop);
43
  pageCountInput.addEventListener('input', updatePageCount);
44
+ overlapInput.addEventListener('input', updateOverlap);
45
+ portraitBtn.addEventListener('click', () => setOrientation('portrait'));
46
  landscapeBtn.addEventListener('click', () => setOrientation('landscape'));
47
  generateBtn.addEventListener('click', generatePosterPages);
48
  downloadAllBtn.addEventListener('click', downloadAllPages);
49
+ downloadPdfBtn.addEventListener('click', generatePDF);
50
 
51
  // Update page count display
52
+ function updatePageCount() {
53
  currentPageCount = parseInt(pageCountInput.value);
54
  pageCountValue.textContent = currentPageCount;
55
  }
56
 
57
  // Set orientation
58
+ // Update overlap value
59
+ function updateOverlap() {
60
+ currentOverlap = parseInt(overlapInput.value);
61
+ overlapValue.textContent = `${currentOverlap}mm`;
62
+ }
63
+
64
  function setOrientation(orientation) {
65
+ currentOrientation = orientation;
66
  if (orientation === 'portrait') {
67
  portraitBtn.classList.add('active', 'bg-indigo-100', 'text-indigo-700');
68
  portraitBtn.classList.remove('border', 'border-gray-300');
 
182
 
183
  // Draw the image on canvas
184
  ctx.drawImage(currentImage, 0, 0, canvas.width, canvas.height);
185
+ // Calculate each page's dimensions with overlap
186
+ const overlapPx = currentOverlap * canvas.width / (cols * 210); // Convert mm to pixels based on scale
187
+ const pageWidth = canvas.width / cols + overlapPx * 2;
188
+ const pageHeight = canvas.height / rows + overlapPx * 2;
189
+ // Create individual pages
 
190
  for (let row = 0; row < rows; row++) {
191
  for (let col = 0; col < cols; col++) {
192
  const pageIndex = row * cols + col;
 
199
  const pageCtx = pageCanvas.getContext('2d');
200
 
201
  // Calculate source dimensions
202
+ const sx = Math.max(0, col * (canvas.width / cols) - overlapPx);
203
+ const sy = Math.max(0, row * (canvas.height / rows) - overlapPx);
204
  const sw = pageWidth;
205
  const sh = pageHeight;
206
+ // Draw the portion of the image on the page
 
207
  pageCtx.drawImage(
208
  canvas,
209
  sx, sy, sw, sh,
 
290
  document.body.removeChild(link);
291
  });
292
  }
293
+
294
+ // Generate PDF with all pages
295
+ function generatePDF() {
296
+ const { jsPDF } = window.jspdf;
297
+ const pdf = new jsPDF({
298
+ orientation: currentOrientation === 'portrait' ? 'p' : 'l',
299
+ unit: 'mm',
300
+ format: 'a4'
301
+ });
302
+
303
+ const pages = posterPages.querySelectorAll('.poster-page img');
304
+
305
+ pages.forEach((img, index) => {
306
+ if (index > 0) {
307
+ pdf.addPage('a4', currentOrientation === 'portrait' ? 'p' : 'l');
308
+ }
309
+
310
+ // Add image to PDF page (A4 dimensions: 210x297mm or 297x210mm)
311
+ const width = currentOrientation === 'portrait' ? 210 : 297;
312
+ const height = currentOrientation === 'portrait' ? 297 : 210;
313
+
314
+ pdf.addImage(img.src, 'JPEG', 0, 0, width, height, undefined, 'FAST');
315
+ });
316
+
317
+ pdf.save('poster-pages.pdf');
318
+ }
319
+ }
320
  });
style.css CHANGED
@@ -7,14 +7,17 @@
7
  .orientation-btn.active {
8
  border: 2px solid #6366f1;
9
  }
10
-
11
  .poster-page {
12
  position: relative;
13
  background-color: white;
14
  overflow: hidden;
15
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
 
16
  }
17
 
 
 
 
18
  .poster-page::before {
19
  content: "";
20
  position: absolute;
 
7
  .orientation-btn.active {
8
  border: 2px solid #6366f1;
9
  }
 
10
  .poster-page {
11
  position: relative;
12
  background-color: white;
13
  overflow: hidden;
14
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
15
+ break-inside: avoid;
16
  }
17
 
18
+ #download-pdf {
19
+ transition: all 0.2s ease;
20
+ }
21
  .poster-page::before {
22
  content: "";
23
  position: absolute;