Malaji71 commited on
Commit
24dabc8
·
verified ·
1 Parent(s): 887561d

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +59 -104
index.html CHANGED
@@ -230,17 +230,16 @@
230
  z-index: 1001;
231
  }
232
 
233
- /* LOADING OVERLAY */
234
  #pdf-loading {
235
  position: fixed; top: 0; left: 0; width: 100%; height: 100%;
236
- background: rgba(0,0,0,0.95);
237
- z-index: 2000;
238
  display: none;
239
  flex-direction: column;
240
  justify-content: center;
241
  align-items: center;
242
  gap: 25px;
243
- backdrop-filter: blur(10px);
244
  }
245
  .spinner {
246
  width: 60px; height: 60px;
@@ -358,9 +357,8 @@
358
  display: flex !important;
359
  opacity: 1 !important;
360
  position: fixed !important;
361
- top: 0 !important;
362
- left: 0 !important;
363
- z-index: 9999 !important;
364
  width: 1920px !important;
365
  height: 1080px !important;
366
  transform: none !important;
@@ -628,82 +626,68 @@
628
  if (e.key === 'ArrowLeft') changeSlide(-1);
629
  });
630
 
631
- // ===================== GENERADOR DE PDF - CON PROGRESO VISUAL =====================
632
  async function generatePDF() {
633
  const loadingOverlay = document.getElementById('pdf-loading');
634
  const progressText = document.getElementById('progress-text');
635
  const btnPdf = document.getElementById('btn-pdf');
636
-
 
 
 
637
  loadingOverlay.style.display = 'flex';
638
  btnPdf.disabled = true;
 
 
 
 
 
 
 
639
 
640
  try {
641
  const { jsPDF } = window.jspdf;
642
- const pdf = new jsPDF({
643
- orientation: 'landscape',
644
- unit: 'px',
645
- format: [1920, 1080],
646
- compress: true
647
- });
648
-
649
- const slides = document.querySelectorAll('.slide');
650
- const originalSlide = currentSlide - 1;
651
 
652
  for (let i = 0; i < slides.length; i++) {
653
  const slide = slides[i];
654
 
655
- // Actualizar mensaje de progreso Y FORZAR RENDERIZADO
656
  progressText.textContent = `Procesando diapositiva ${i + 1} de ${slides.length}...`;
657
-
658
- // Forzar reflow para que el navegador actualice el DOM
659
- void progressText.offsetWidth;
660
-
661
- // Pequeña pausa para permitir que el navegador renderice el cambio
662
- await new Promise(resolve => setTimeout(resolve, 100));
663
-
664
- // 1. Activar modo captura: mostrar SOLO esta slide con estilos forzados
665
- slides.forEach((s, idx) => {
666
- s.classList.toggle('capture-mode', idx === i);
667
- s.style.display = idx === i ? 'flex' : 'none';
668
- });
669
-
670
- // 2. Forzar estado final de animaciones
671
  const animatedElements = slide.querySelectorAll('[class*="animate-"]');
672
  animatedElements.forEach(el => {
673
  el.style.animation = 'none';
674
  el.style.opacity = '1';
675
  el.style.transform = 'none';
676
- void el.offsetWidth; // Forzar reflow
677
  });
678
-
679
- // 3. Recolectar todos los links con sus posiciones
680
  const links = [];
681
- const linkElements = slide.querySelectorAll('a[href]');
682
- linkElements.forEach(link => {
683
  const rect = link.getBoundingClientRect();
684
  const href = link.getAttribute('href');
685
  if (href && !href.startsWith('#')) {
686
- links.push({
687
- x: rect.left,
688
- y: rect.top,
689
- width: rect.width,
690
- height: rect.height,
691
- url: href
692
- });
693
  }
694
  });
695
-
696
- // 4. Esperar renderizado completo
697
  await new Promise(resolve => setTimeout(resolve, 1500));
698
-
699
- // 5. Convertir imagen de fondo a base64 para evitar CORS
700
  const bgStyle = window.getComputedStyle(slide).backgroundImage;
701
  const urlMatch = bgStyle.match(/url\(["']?(.*?)["']?\)/);
702
-
703
  if (urlMatch && urlMatch[1]) {
704
  try {
705
- const cleanUrl = urlMatch[1];
706
- const res = await fetch(cleanUrl);
707
  const blob = await res.blob();
708
  const b64 = await new Promise(r => {
709
  const rd = new FileReader();
@@ -711,71 +695,42 @@
711
  rd.readAsDataURL(blob);
712
  });
713
  slide.style.backgroundImage = `url(${b64})`;
714
- } catch (e) {
715
- console.warn("No se pudo convertir imagen de fondo:", e);
716
- }
717
  }
718
-
719
- // 6. Capturar con html2canvas - configuración optimizada
720
  const canvas = await html2canvas(slide, {
721
- scale: 1,
722
- useCORS: false,
723
- allowTaint: false,
724
- backgroundColor: '#050505',
725
- logging: false,
726
- width: 1920,
727
- height: 1080,
728
- windowWidth: 1920,
729
- windowHeight: 1080,
730
- scrollX: 0,
731
- scrollY: 0,
732
- x: 0,
733
- y: 0,
734
- foreignObjectRendering: true,
735
- removeContainer: true
736
  });
737
-
738
- // 7. Añadir al PDF
739
  if (i > 0) pdf.addPage();
740
- const imgData = canvas.toDataURL('image/jpeg', 0.95);
741
- pdf.addImage(imgData, 'JPEG', 0, 0, 1920, 1080, undefined, 'FAST');
742
-
743
- // 8. Agregar links activos sobre la imagen
744
  links.forEach(link => {
745
- // Ajustar coordenadas al tamaño del PDF (1920x1080)
746
- const pdfLink = {
747
- x: link.x,
748
- y: link.y,
749
- w: link.width,
750
- h: link.height,
751
- url: link.url
752
- };
753
-
754
- // Agregar link al PDF
755
- pdf.link(pdfLink.x, pdfLink.y, pdfLink.w, pdfLink.h, {
756
- url: pdfLink.url
757
- });
758
  });
 
 
 
 
759
  }
760
 
761
- // 9. Restaurar estado original
762
- slides.forEach((s, idx) => {
763
- s.classList.remove('capture-mode');
764
- s.style.display = idx === originalSlide ? 'flex' : 'none';
765
- });
766
-
767
  progressText.textContent = 'Finalizando y descargando...';
768
  await new Promise(resolve => setTimeout(resolve, 500));
769
-
770
- // 10. Guardar PDF
771
  pdf.save('MIGUEL_PitchDeck.pdf');
772
-
773
- // 11. Recargar para restaurar animaciones originales
 
 
 
774
  setTimeout(() => location.reload(), 1000);
775
-
776
  } catch (err) {
777
- console.error('Error detallado:', err);
778
- alert('Hubo un error al generar el PDF: ' + err.message);
779
  } finally {
780
  loadingOverlay.style.display = 'none';
781
  btnPdf.disabled = false;
 
230
  z-index: 1001;
231
  }
232
 
233
+ /* LOADING OVERLAY - NEGRO SÓLIDO Y CAPA SUPERIOR ABSOLUTA */
234
  #pdf-loading {
235
  position: fixed; top: 0; left: 0; width: 100%; height: 100%;
236
+ background: #000000; /* Sin transparencia, bloquea todo */
237
+ z-index: 99999; /* Por encima de cualquier elemento */
238
  display: none;
239
  flex-direction: column;
240
  justify-content: center;
241
  align-items: center;
242
  gap: 25px;
 
243
  }
244
  .spinner {
245
  width: 60px; height: 60px;
 
357
  display: flex !important;
358
  opacity: 1 !important;
359
  position: fixed !important;
360
+ top: 0 !important; left: 0 !important;
361
+ z-index: 1 !important; /* Siempre debajo del overlay */
 
362
  width: 1920px !important;
363
  height: 1080px !important;
364
  transform: none !important;
 
626
  if (e.key === 'ArrowLeft') changeSlide(-1);
627
  });
628
 
629
+ // ===================== GENERADOR DE PDF - UX OPTIMIZADA =====================
630
  async function generatePDF() {
631
  const loadingOverlay = document.getElementById('pdf-loading');
632
  const progressText = document.getElementById('progress-text');
633
  const btnPdf = document.getElementById('btn-pdf');
634
+ const slides = document.querySelectorAll('.slide');
635
+ const originalSlide = currentSlide - 1;
636
+
637
+ // 1. Mostrar overlay INMEDIATAMENTE
638
  loadingOverlay.style.display = 'flex';
639
  btnPdf.disabled = true;
640
+ progressText.textContent = 'Inicializando...';
641
+
642
+ // 2. Ocultar TODAS las slides para que NO se vean detrás
643
+ slides.forEach(s => s.style.display = 'none');
644
+
645
+ // 3. Forzar repaint del navegador ANTES de procesar
646
+ await new Promise(resolve => setTimeout(resolve, 200));
647
 
648
  try {
649
  const { jsPDF } = window.jspdf;
650
+ const pdf = new jsPDF({ orientation: 'landscape', unit: 'px', format: [1920, 1080], compress: true });
 
 
 
 
 
 
 
 
651
 
652
  for (let i = 0; i < slides.length; i++) {
653
  const slide = slides[i];
654
 
655
+ // Actualizar progreso y permitir repaint
656
  progressText.textContent = `Procesando diapositiva ${i + 1} de ${slides.length}...`;
657
+ await new Promise(resolve => setTimeout(resolve, 50));
658
+
659
+ // Activar modo captura
660
+ slide.classList.add('capture-mode');
661
+ slide.style.display = 'flex';
662
+
663
+ // Forzar animaciones a estado final
 
 
 
 
 
 
 
664
  const animatedElements = slide.querySelectorAll('[class*="animate-"]');
665
  animatedElements.forEach(el => {
666
  el.style.animation = 'none';
667
  el.style.opacity = '1';
668
  el.style.transform = 'none';
669
+ void el.offsetWidth;
670
  });
671
+
672
+ // Recolectar links
673
  const links = [];
674
+ slide.querySelectorAll('a[href]').forEach(link => {
 
675
  const rect = link.getBoundingClientRect();
676
  const href = link.getAttribute('href');
677
  if (href && !href.startsWith('#')) {
678
+ links.push({ x: rect.left, y: rect.top, width: rect.width, height: rect.height, url: href });
 
 
 
 
 
 
679
  }
680
  });
681
+
682
+ // Esperar renderizado
683
  await new Promise(resolve => setTimeout(resolve, 1500));
684
+
685
+ // Convertir bg a base64
686
  const bgStyle = window.getComputedStyle(slide).backgroundImage;
687
  const urlMatch = bgStyle.match(/url\(["']?(.*?)["']?\)/);
 
688
  if (urlMatch && urlMatch[1]) {
689
  try {
690
+ const res = await fetch(urlMatch[1]);
 
691
  const blob = await res.blob();
692
  const b64 = await new Promise(r => {
693
  const rd = new FileReader();
 
695
  rd.readAsDataURL(blob);
696
  });
697
  slide.style.backgroundImage = `url(${b64})`;
698
+ } catch (e) { console.warn("BG conversion failed:", e); }
 
 
699
  }
700
+
701
+ // Capturar
702
  const canvas = await html2canvas(slide, {
703
+ scale: 1, useCORS: false, allowTaint: false, backgroundColor: '#050505',
704
+ logging: false, width: 1920, height: 1080, windowWidth: 1920, windowHeight: 1080,
705
+ scrollX: 0, scrollY: 0, x: 0, y: 0, foreignObjectRendering: true, removeContainer: true
 
 
 
 
 
 
 
 
 
 
 
 
706
  });
707
+
 
708
  if (i > 0) pdf.addPage();
709
+ pdf.addImage(canvas.toDataURL('image/jpeg', 0.95), 'JPEG', 0, 0, 1920, 1080, undefined, 'FAST');
710
+
711
+ // Agregar links
 
712
  links.forEach(link => {
713
+ pdf.link(link.x, link.y, link.width, link.height, { url: link.url });
 
 
 
 
 
 
 
 
 
 
 
 
714
  });
715
+
716
+ // Ocultar slide inmediatamente después de capturar
717
+ slide.classList.remove('capture-mode');
718
+ slide.style.display = 'none';
719
  }
720
 
 
 
 
 
 
 
721
  progressText.textContent = 'Finalizando y descargando...';
722
  await new Promise(resolve => setTimeout(resolve, 500));
 
 
723
  pdf.save('MIGUEL_PitchDeck.pdf');
724
+
725
+ // Restaurar slide original
726
+ slides.forEach((s, idx) => {
727
+ s.style.display = idx === originalSlide ? 'flex' : 'none';
728
+ });
729
  setTimeout(() => location.reload(), 1000);
730
+
731
  } catch (err) {
732
+ console.error('Error:', err);
733
+ alert('Error al generar PDF: ' + err.message);
734
  } finally {
735
  loadingOverlay.style.display = 'none';
736
  btnPdf.disabled = false;