Lashtw commited on
Commit
6adf160
·
verified ·
1 Parent(s): 8ebc1d1

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +62 -41
index.html CHANGED
@@ -446,11 +446,6 @@
446
  class="grid-cell relative border border-slate-300 cursor-pointer hover:bg-slate-50 select-none"
447
  :class="{ 'ring-4 ring-indigo-500 ring-inset z-20': selectedCellIndex === index }"
448
  >
449
- <!-- Grid Coordinate -->
450
- <span class="absolute top-1 left-1 text-[8px] text-slate-200 pointer-events-none z-10">
451
- {{ Math.floor(index / currentGrid.cols) + 1 }}-{{ (index % currentGrid.cols) + 1 }}
452
- </span>
453
-
454
  <div class="rotation-wrapper pointer-events-none" :style="{ transform: `rotate(${cell.rotation}deg)` }">
455
  <span v-if="cell.type === 'text'" class="text-4xl md:text-5xl font-bold cell-text block" :style="{ color: cell.color }">
456
  {{ cell.content }}
@@ -908,6 +903,52 @@
908
  return content.replace(/['"]/g, '');
909
  };
910
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
911
  // ... PDF Export Logic ...
912
  const renderPageToCanvas = async (pageId) => {
913
  const pageData = pages.value[pageId - 1];
@@ -931,7 +972,7 @@
931
  // Text uses the SVG text replacement trick for perfect centering
932
  contentHtml = `<span class="export-text" data-color="${cell.color}" style="font-size: 40px; font-weight: bold; color: ${cell.color}; font-family: 'Noto Sans TC', sans-serif;">${cell.content}</span>`;
933
  } else if (cell.type === 'icon') {
934
- // FontAwesome Icons -> Convert to Unicode Char + SVG Text Trick
935
  // This ensures the icon behaves exactly like text (perfectly centered, rotates well)
936
  const iconClass = icons[cell.content];
937
  const unicode = getIconUnicode(iconClass);
@@ -941,11 +982,10 @@
941
  contentHtml = `<img src="${cell.content}" style="width: 80%; height: 80%; object-fit: contain;">`;
942
  }
943
 
944
- const coord = `${Math.floor(idx / cols) + 1}-${(idx % cols) + 1}`;
945
 
946
  gridHtml += `
947
  <div class="grid-cell" style="position: relative; border: 1px solid #cbd5e1; display: flex; align-items: center; justify-content: center; overflow: hidden;">
948
- <span style="position: absolute; top: 4px; left: 4px; font-size: 8px; color: #e2e8f0;">${coord}</span>
949
  <div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; transform: rotate(${cell.rotation}deg);">
950
  ${contentHtml}
951
  </div>
@@ -973,14 +1013,25 @@
973
  replaceWithSvgText(el, textContent, color, "'Noto Sans TC', sans-serif", "bold");
974
  });
975
 
976
- // Handle Icon Centering (Same trick!)
977
  const iconElements = clonedDoc.querySelectorAll('.export-icon');
978
  iconElements.forEach(el => {
979
  const textContent = el.innerText;
980
  const color = el.getAttribute('data-color');
981
  if (!textContent) return;
982
- // FontAwesome solid needs font-weight 900
983
- replaceWithSvgText(el, textContent, color, "'Font Awesome 6 Free'", "900");
 
 
 
 
 
 
 
 
 
 
 
984
  });
985
  }
986
  });
@@ -988,36 +1039,6 @@
988
  return canvas;
989
  };
990
 
991
- // Helper to replace text element with SVG for perfect centering
992
- const replaceWithSvgText = (el, content, color, fontFamily, fontWeight) => {
993
- const ns = "http://www.w3.org/2000/svg";
994
- const svg = document.createElementNS(ns, "svg");
995
- svg.setAttribute("width", "100%");
996
- svg.setAttribute("height", "100%");
997
- svg.setAttribute("viewBox", "0 0 100 100");
998
- svg.style.position = "absolute";
999
- svg.style.top = "0";
1000
- svg.style.left = "0";
1001
-
1002
- const textNode = document.createElementNS(ns, "text");
1003
- textNode.setAttribute("x", "50%");
1004
- textNode.setAttribute("y", "50%");
1005
- textNode.setAttribute("dominant-baseline", "central");
1006
- textNode.setAttribute("text-anchor", "middle");
1007
- textNode.setAttribute("fill", color);
1008
- textNode.setAttribute("font-family", fontFamily);
1009
- textNode.setAttribute("font-weight", fontWeight);
1010
- textNode.setAttribute("font-size", "45");
1011
- textNode.textContent = content;
1012
-
1013
- svg.appendChild(textNode);
1014
-
1015
- const parent = el.parentNode;
1016
- parent.style.position = "relative";
1017
- parent.innerHTML = '';
1018
- parent.appendChild(svg);
1019
- };
1020
-
1021
  const exportPDF = async () => {
1022
  if (selectedCellIndex.value !== null) selectedCellIndex.value = null;
1023
  isGenerating.value = true;
 
446
  class="grid-cell relative border border-slate-300 cursor-pointer hover:bg-slate-50 select-none"
447
  :class="{ 'ring-4 ring-indigo-500 ring-inset z-20': selectedCellIndex === index }"
448
  >
 
 
 
 
 
449
  <div class="rotation-wrapper pointer-events-none" :style="{ transform: `rotate(${cell.rotation}deg)` }">
450
  <span v-if="cell.type === 'text'" class="text-4xl md:text-5xl font-bold cell-text block" :style="{ color: cell.color }">
451
  {{ cell.content }}
 
903
  return content.replace(/['"]/g, '');
904
  };
905
 
906
+ // Helper to convert text (or icon) to image data URL
907
+ const textToImage = (text, color, font) => {
908
+ const canvas = document.createElement('canvas');
909
+ // Increase resolution for print quality
910
+ canvas.width = 150;
911
+ canvas.height = 150;
912
+ const ctx = canvas.getContext('2d');
913
+ ctx.font = font;
914
+ ctx.fillStyle = color;
915
+ ctx.textAlign = 'center';
916
+ ctx.textBaseline = 'middle';
917
+ // Draw
918
+ ctx.fillText(text, 75, 75);
919
+ return canvas.toDataURL('image/png');
920
+ };
921
+
922
+ // Helper to replace text element with SVG for perfect centering
923
+ const replaceWithSvgText = (el, content, color, fontFamily, fontWeight) => {
924
+ const ns = "http://www.w3.org/2000/svg";
925
+ const svg = document.createElementNS(ns, "svg");
926
+ svg.setAttribute("width", "100%");
927
+ svg.setAttribute("height", "100%");
928
+ svg.setAttribute("viewBox", "0 0 100 100");
929
+ svg.style.position = "absolute";
930
+ svg.style.top = "0";
931
+ svg.style.left = "0";
932
+
933
+ const textNode = document.createElementNS(ns, "text");
934
+ textNode.setAttribute("x", "50%");
935
+ textNode.setAttribute("y", "50%");
936
+ textNode.setAttribute("dominant-baseline", "central");
937
+ textNode.setAttribute("text-anchor", "middle");
938
+ textNode.setAttribute("fill", color);
939
+ textNode.setAttribute("font-family", fontFamily);
940
+ textNode.setAttribute("font-weight", fontWeight);
941
+ textNode.setAttribute("font-size", "45");
942
+ textNode.textContent = content;
943
+
944
+ svg.appendChild(textNode);
945
+
946
+ const parent = el.parentNode;
947
+ parent.style.position = "relative";
948
+ parent.innerHTML = '';
949
+ parent.appendChild(svg);
950
+ };
951
+
952
  // ... PDF Export Logic ...
953
  const renderPageToCanvas = async (pageId) => {
954
  const pageData = pages.value[pageId - 1];
 
972
  // Text uses the SVG text replacement trick for perfect centering
973
  contentHtml = `<span class="export-text" data-color="${cell.color}" style="font-size: 40px; font-weight: bold; color: ${cell.color}; font-family: 'Noto Sans TC', sans-serif;">${cell.content}</span>`;
974
  } else if (cell.type === 'icon') {
975
+ // FontAwesome Icons -> Convert to Unicode Char
976
  // This ensures the icon behaves exactly like text (perfectly centered, rotates well)
977
  const iconClass = icons[cell.content];
978
  const unicode = getIconUnicode(iconClass);
 
982
  contentHtml = `<img src="${cell.content}" style="width: 80%; height: 80%; object-fit: contain;">`;
983
  }
984
 
985
+ // Coordinate span REMOVED here
986
 
987
  gridHtml += `
988
  <div class="grid-cell" style="position: relative; border: 1px solid #cbd5e1; display: flex; align-items: center; justify-content: center; overflow: hidden;">
 
989
  <div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; transform: rotate(${cell.rotation}deg);">
990
  ${contentHtml}
991
  </div>
 
1013
  replaceWithSvgText(el, textContent, color, "'Noto Sans TC', sans-serif", "bold");
1014
  });
1015
 
1016
+ // Handle Icon Centering via Image conversion (Fixes PDF box issue)
1017
  const iconElements = clonedDoc.querySelectorAll('.export-icon');
1018
  iconElements.forEach(el => {
1019
  const textContent = el.innerText;
1020
  const color = el.getAttribute('data-color');
1021
  if (!textContent) return;
1022
+
1023
+ // Convert to image using canvas in main thread context
1024
+ // 'Font Awesome 6 Free' must be loaded in the page
1025
+ const imgData = textToImage(textContent, color, "900 100px 'Font Awesome 6 Free'");
1026
+
1027
+ const img = document.createElement('img');
1028
+ img.src = imgData;
1029
+ img.style.width = '100%';
1030
+ img.style.height = '100%';
1031
+ img.style.objectFit = 'contain';
1032
+
1033
+ el.parentNode.innerHTML = ''; // Clear parent
1034
+ el.parentNode.appendChild(img);
1035
  });
1036
  }
1037
  });
 
1039
  return canvas;
1040
  };
1041
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1042
  const exportPDF = async () => {
1043
  if (selectedCellIndex.value !== null) selectedCellIndex.value = null;
1044
  isGenerating.value = true;