Update index.html
Browse files- index.html +39 -19
index.html
CHANGED
|
@@ -307,7 +307,7 @@
|
|
| 307 |
</div>
|
| 308 |
<!-- Background Color (Macaron) -->
|
| 309 |
<div>
|
| 310 |
-
<label class="block text-sm font-bold text-slate-700 mb-2">2.
|
| 311 |
<div class="flex flex-wrap gap-2">
|
| 312 |
<button
|
| 313 |
v-for="bgColor in bgColors"
|
|
@@ -565,9 +565,13 @@
|
|
| 565 |
v-for="(cell, index) in pages[pageId-1].cells"
|
| 566 |
:key="cell.id"
|
| 567 |
class="grid-cell relative border border-slate-300"
|
| 568 |
-
:style="{ backgroundColor: cell.bgColor }"
|
| 569 |
>
|
| 570 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 571 |
<span v-if="cell.type === 'text'" class="font-bold cell-text" :class="getOverviewFontSizeClass(cell.content)" :style="{ color: cell.color }">{{ cell.content }}</span>
|
| 572 |
|
| 573 |
<!-- Render Icon: Emoji -->
|
|
@@ -613,15 +617,19 @@
|
|
| 613 |
@click="handleCellClick(index, $event)"
|
| 614 |
class="grid-cell relative border border-slate-300 cursor-pointer hover:bg-slate-50 select-none"
|
| 615 |
:class="{ 'ring-4 ring-indigo-500 ring-inset z-20': selectedCellIndices.has(index) }"
|
| 616 |
-
:style="{ backgroundColor: cell.bgColor }"
|
| 617 |
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 618 |
<!-- Selection Order Badge (Only visible in Multi-Select Mode when selected) -->
|
| 619 |
<div v-if="isMultiSelectMode && selectedCellIndices.has(index)"
|
| 620 |
class="absolute top-1 right-1 w-6 h-6 bg-indigo-600 text-white rounded-full flex items-center justify-center text-xs font-bold z-30 shadow-sm border-2 border-white">
|
| 621 |
{{ getSelectionOrder(index) }}
|
| 622 |
</div>
|
| 623 |
|
| 624 |
-
<div class="rotation-wrapper pointer-events-none" :style="{ transform: `rotate(${cell.rotation}deg)` }">
|
| 625 |
<span v-if="cell.type === 'text'" class="font-bold cell-text block" :class="getFontSizeClass(cell.content)" :style="{ color: cell.color }">
|
| 626 |
{{ cell.content }}
|
| 627 |
</span>
|
|
@@ -1437,9 +1445,16 @@
|
|
| 1437 |
contentHtml = `<img src="${cell.content}" style="width: 80%; height: 80%; object-fit: contain;">`;
|
| 1438 |
}
|
| 1439 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1440 |
gridHtml += `
|
| 1441 |
-
<div class="grid-cell" style="position: relative; ${borderStyle} background-color:
|
| 1442 |
-
|
|
|
|
| 1443 |
${contentHtml}
|
| 1444 |
</div>
|
| 1445 |
</div>
|
|
@@ -1550,23 +1565,28 @@
|
|
| 1550 |
const x = c * cellW;
|
| 1551 |
const y = r * cellH;
|
| 1552 |
|
| 1553 |
-
// 1. Background
|
| 1554 |
if (cell.bgColor !== '#ffffff') {
|
| 1555 |
-
|
| 1556 |
-
|
|
|
|
|
|
|
|
|
|
| 1557 |
fill: { color: cell.bgColor.replace('#', '') },
|
| 1558 |
-
line: {
|
| 1559 |
-
|
| 1560 |
-
} else {
|
| 1561 |
-
// Transparent/White bg but need grid lines
|
| 1562 |
-
slide.addShape(pres.ShapeType.rect, {
|
| 1563 |
-
x: x, y: y, w: cellW, h: cellH,
|
| 1564 |
-
fill: { color: 'FFFFFF' },
|
| 1565 |
-
line: { color: 'CCCCCC', width: 0.5 }
|
| 1566 |
});
|
| 1567 |
}
|
| 1568 |
|
| 1569 |
-
// 2.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1570 |
if (cell.content) {
|
| 1571 |
if (cell.type === 'text' || cell.type === 'icon') {
|
| 1572 |
let content = cell.content;
|
|
|
|
| 307 |
</div>
|
| 308 |
<!-- Background Color (Macaron) -->
|
| 309 |
<div>
|
| 310 |
+
<label class="block text-sm font-bold text-slate-700 mb-2">2. 背景網底 (淺色系)</label>
|
| 311 |
<div class="flex flex-wrap gap-2">
|
| 312 |
<button
|
| 313 |
v-for="bgColor in bgColors"
|
|
|
|
| 565 |
v-for="(cell, index) in pages[pageId-1].cells"
|
| 566 |
:key="cell.id"
|
| 567 |
class="grid-cell relative border border-slate-300"
|
|
|
|
| 568 |
>
|
| 569 |
+
<!-- Inner Background (Highlight) -->
|
| 570 |
+
<div class="absolute inset-0 flex items-center justify-center pointer-events-none z-0">
|
| 571 |
+
<div v-if="cell.bgColor !== '#ffffff'" class="w-[85%] h-[85%] rounded-lg transition-colors" :style="{ backgroundColor: cell.bgColor }"></div>
|
| 572 |
+
</div>
|
| 573 |
+
|
| 574 |
+
<div class="rotation-wrapper relative z-10" :style="{ transform: `rotate(${cell.rotation}deg)` }">
|
| 575 |
<span v-if="cell.type === 'text'" class="font-bold cell-text" :class="getOverviewFontSizeClass(cell.content)" :style="{ color: cell.color }">{{ cell.content }}</span>
|
| 576 |
|
| 577 |
<!-- Render Icon: Emoji -->
|
|
|
|
| 617 |
@click="handleCellClick(index, $event)"
|
| 618 |
class="grid-cell relative border border-slate-300 cursor-pointer hover:bg-slate-50 select-none"
|
| 619 |
:class="{ 'ring-4 ring-indigo-500 ring-inset z-20': selectedCellIndices.has(index) }"
|
|
|
|
| 620 |
>
|
| 621 |
+
<!-- Inner Background (Highlight) -->
|
| 622 |
+
<div class="absolute inset-0 flex items-center justify-center pointer-events-none z-0">
|
| 623 |
+
<div v-if="cell.bgColor !== '#ffffff'" class="w-[85%] h-[85%] rounded-lg transition-colors" :style="{ backgroundColor: cell.bgColor }"></div>
|
| 624 |
+
</div>
|
| 625 |
+
|
| 626 |
<!-- Selection Order Badge (Only visible in Multi-Select Mode when selected) -->
|
| 627 |
<div v-if="isMultiSelectMode && selectedCellIndices.has(index)"
|
| 628 |
class="absolute top-1 right-1 w-6 h-6 bg-indigo-600 text-white rounded-full flex items-center justify-center text-xs font-bold z-30 shadow-sm border-2 border-white">
|
| 629 |
{{ getSelectionOrder(index) }}
|
| 630 |
</div>
|
| 631 |
|
| 632 |
+
<div class="rotation-wrapper pointer-events-none relative z-10" :style="{ transform: `rotate(${cell.rotation}deg)` }">
|
| 633 |
<span v-if="cell.type === 'text'" class="font-bold cell-text block" :class="getFontSizeClass(cell.content)" :style="{ color: cell.color }">
|
| 634 |
{{ cell.content }}
|
| 635 |
</span>
|
|
|
|
| 1445 |
contentHtml = `<img src="${cell.content}" style="width: 80%; height: 80%; object-fit: contain;">`;
|
| 1446 |
}
|
| 1447 |
|
| 1448 |
+
// New: Inner Highlight for PDF Export
|
| 1449 |
+
let innerBg = '';
|
| 1450 |
+
if (cell.bgColor && cell.bgColor !== '#ffffff') {
|
| 1451 |
+
innerBg = `<div style="position: absolute; top: 7.5%; left: 7.5%; width: 85%; height: 85%; background-color: ${cell.bgColor}; border-radius: 8px; z-index: 0;"></div>`;
|
| 1452 |
+
}
|
| 1453 |
+
|
| 1454 |
gridHtml += `
|
| 1455 |
+
<div class="grid-cell" style="position: relative; ${borderStyle} background-color: transparent; display: flex; align-items: center; justify-content: center; overflow: hidden;">
|
| 1456 |
+
${innerBg}
|
| 1457 |
+
<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; transform: rotate(${cell.rotation}deg); z-index: 1; position: relative;">
|
| 1458 |
${contentHtml}
|
| 1459 |
</div>
|
| 1460 |
</div>
|
|
|
|
| 1565 |
const x = c * cellW;
|
| 1566 |
const y = r * cellH;
|
| 1567 |
|
| 1568 |
+
// 1. Highlight (Inner Background)
|
| 1569 |
if (cell.bgColor !== '#ffffff') {
|
| 1570 |
+
const padW = cellW * 0.075; // 7.5% padding
|
| 1571 |
+
const padH = cellH * 0.075;
|
| 1572 |
+
slide.addShape(pres.ShapeType.roundRect, {
|
| 1573 |
+
x: x + padW, y: y + padH,
|
| 1574 |
+
w: cellW * 0.85, h: cellH * 0.85,
|
| 1575 |
fill: { color: cell.bgColor.replace('#', '') },
|
| 1576 |
+
line: { type: 'none' }, // No border on highlight
|
| 1577 |
+
rectRadius: 0.2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1578 |
});
|
| 1579 |
}
|
| 1580 |
|
| 1581 |
+
// 2. Grid Border (Always draw transparent rect with border)
|
| 1582 |
+
// This ensures grid lines are visible and clean
|
| 1583 |
+
slide.addShape(pres.ShapeType.rect, {
|
| 1584 |
+
x: x, y: y, w: cellW, h: cellH,
|
| 1585 |
+
fill: { type: 'none' },
|
| 1586 |
+
line: { color: 'CCCCCC', width: 0.5 }
|
| 1587 |
+
});
|
| 1588 |
+
|
| 1589 |
+
// 3. Content
|
| 1590 |
if (cell.content) {
|
| 1591 |
if (cell.type === 'text' || cell.type === 'icon') {
|
| 1592 |
let content = cell.content;
|