Lashtw commited on
Commit
dddcc42
·
verified ·
1 Parent(s): 737c7fe

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +33 -19
index.html CHANGED
@@ -199,11 +199,9 @@
199
  display: flex;
200
  flex-direction: column;
201
  overflow: hidden;
202
- transition: border 0.2s, box-shadow 0.2s;
203
  touch-action: none;
204
  }
205
 
206
- /* 4 大分類的主題代表色 */
207
  .board-card[data-cat="exam"] {
208
  --theme-color: #38bdf8;
209
  --num-color: #38bdf8;
@@ -236,7 +234,6 @@
236
  z-index: 2;
237
  }
238
 
239
- /* 重點高亮卡片:覆蓋為極致琥珀金強調色 */
240
  .board-card.highlight {
241
  border: 1.8px solid #fbbf24;
242
  box-shadow: 0 16px 40px rgba(251, 191, 36, 0.28);
@@ -300,7 +297,6 @@
300
  padding-left: 2px;
301
  }
302
 
303
- /* 數字文字色彩重新連動主題色 */
304
  .card-center-metric {
305
  flex: 1;
306
  display: flex;
@@ -341,7 +337,7 @@
341
  height: 100%;
342
  background: var(--theme-color);
343
  border-radius: 999px;
344
- transition: width 0.4s ease;
345
  }
346
  .metric-details {
347
  display: flex;
@@ -375,17 +371,18 @@
375
  cursor: grabbing;
376
  }
377
 
 
378
  .resize-handle {
379
  display: none;
380
  position: absolute;
381
  right: 0px;
382
  bottom: 0px;
383
- width: 38px;
384
- height: 38px;
385
  cursor: se-resize;
386
- background: radial-gradient(circle at 75% 75%, #38bdf8 0%, transparent 65%);
387
- border-bottom-right-radius: 20px;
388
- z-index: 10;
389
  touch-action: none;
390
  pointer-events: auto;
391
  }
@@ -931,7 +928,7 @@
931
  document.body.removeChild(a);
932
  URL.revokeObjectURL(url);
933
 
934
- alert("✓ 固化成功!請用剛下載的 `index.html` 直接覆蓋 Lively 資料夾內的原檔,開機將永久預設此版面。");
935
  }
936
 
937
  function openPinModal() {
@@ -1101,8 +1098,7 @@
1101
  <span class="metric-unit">天</span>
1102
  </div>
1103
 
1104
- ${isTall ? `
1105
- <div class="card-dynamic-body">
1106
  <div class="progress-track">
1107
  <div class="progress-fill" style="width: ${progressPct}%;"></div>
1108
  </div>
@@ -1111,7 +1107,6 @@
1111
  <span>約合 <b>${weeksLeft}</b> 週</span>
1112
  </div>
1113
  </div>
1114
- ` : ''}
1115
 
1116
  <div class="card-badge-wrap">
1117
  <div class="status-capsule">${badgeText}</div>
@@ -1125,9 +1120,13 @@
1125
  });
1126
  }
1127
 
 
 
 
1128
  function attachTouchAndPointerEvents(cardEl, cardData) {
1129
  const resizeHandle = cardEl.querySelector('.resize-handle');
1130
 
 
1131
  cardEl.addEventListener('pointerdown', (e) => {
1132
  if (!isEditing) return;
1133
  if (e.target === resizeHandle || e.target.classList.contains('resize-handle')) return;
@@ -1170,6 +1169,7 @@
1170
  cardEl.addEventListener('pointercancel', onPointerUp);
1171
  });
1172
 
 
1173
  resizeHandle.addEventListener('pointerdown', (e) => {
1174
  if (!isEditing) return;
1175
  e.stopPropagation();
@@ -1181,17 +1181,31 @@
1181
  let startW = cardEl.offsetWidth;
1182
  let startH = cardEl.offsetHeight;
1183
 
 
 
 
1184
  function onResizeMove(ev) {
1185
  if (ev.pointerId !== e.pointerId) return;
1186
  ev.preventDefault();
 
 
1187
  const newW = Math.max(240, startW + (ev.clientX - startX));
1188
  const newH = Math.max(180, startH + (ev.clientY - startY));
1189
 
 
1190
  cardEl.style.width = `${newW}px`;
1191
  cardEl.style.height = `${newH}px`;
1192
  cardData.w = newW;
1193
  cardData.h = newH;
1194
- renderBoard();
 
 
 
 
 
 
 
 
1195
  }
1196
 
1197
  function onResizeUp(ev) {
@@ -1200,7 +1214,10 @@
1200
  resizeHandle.removeEventListener('pointermove', onResizeMove);
1201
  resizeHandle.removeEventListener('pointerup', onResizeUp);
1202
  resizeHandle.removeEventListener('pointercancel', onResizeUp);
 
 
1203
  saveAppData();
 
1204
  }
1205
 
1206
  resizeHandle.addEventListener('pointermove', onResizeMove);
@@ -1209,7 +1226,7 @@
1209
  });
1210
  }
1211
 
1212
- // 極光引擎 (支援多重高亮焦點光暈)
1213
  const canvas = document.getElementById("aurora-canvas");
1214
  const ctx = canvas.getContext("2d");
1215
  let animId = null;
@@ -1226,7 +1243,6 @@
1226
  ctx.clearRect(0, 0, canvas.width, canvas.height);
1227
  step += 0.008;
1228
 
1229
- // 抓取所有被設為高亮的卡片
1230
  const highlightCards = appState.cards.filter(c => c.highlight);
1231
  const primaryHighlight = highlightCards[0];
1232
  const focalX = primaryHighlight ? (primaryHighlight.x + primaryHighlight.w / 2) : canvas.width * 0.7;
@@ -1271,7 +1287,6 @@
1271
  ctx.filter = "none";
1272
  });
1273
 
1274
- // 為所有複選高亮的卡片同時繪製共振金色光暈
1275
  highlightCards.forEach(c => {
1276
  const cx = c.x + c.w / 2;
1277
  const cy = c.y + c.h / 2;
@@ -1391,7 +1406,6 @@
1391
  });
1392
  }
1393
 
1394
- // 支援複選高亮
1395
  function toggleCardHighlight(idx, isChecked) {
1396
  appState.cards[idx].highlight = isChecked;
1397
  renderBoard();
 
199
  display: flex;
200
  flex-direction: column;
201
  overflow: hidden;
 
202
  touch-action: none;
203
  }
204
 
 
205
  .board-card[data-cat="exam"] {
206
  --theme-color: #38bdf8;
207
  --num-color: #38bdf8;
 
234
  z-index: 2;
235
  }
236
 
 
237
  .board-card.highlight {
238
  border: 1.8px solid #fbbf24;
239
  box-shadow: 0 16px 40px rgba(251, 191, 36, 0.28);
 
297
  padding-left: 2px;
298
  }
299
 
 
300
  .card-center-metric {
301
  flex: 1;
302
  display: flex;
 
337
  height: 100%;
338
  background: var(--theme-color);
339
  border-radius: 999px;
340
+ transition: width 0.2s ease;
341
  }
342
  .metric-details {
343
  display: flex;
 
371
  cursor: grabbing;
372
  }
373
 
374
+ /* 放大把手並加強視覺指引 */
375
  .resize-handle {
376
  display: none;
377
  position: absolute;
378
  right: 0px;
379
  bottom: 0px;
380
+ width: 42px;
381
+ height: 42px;
382
  cursor: se-resize;
383
+ background: radial-gradient(circle at 75% 75%, rgba(56, 189, 248, 0.9) 0%, transparent 68%);
384
+ border-bottom-right-radius: 24px;
385
+ z-index: 20;
386
  touch-action: none;
387
  pointer-events: auto;
388
  }
 
928
  document.body.removeChild(a);
929
  URL.revokeObjectURL(url);
930
 
931
+ alert("✓ 固化成功!請用剛下載的 `index.html` 直接覆蓋原檔,開機將永久預設此版面。");
932
  }
933
 
934
  function openPinModal() {
 
1098
  <span class="metric-unit">天</span>
1099
  </div>
1100
 
1101
+ <div class="card-dynamic-body" style="display: ${isTall ? 'flex' : 'none'};">
 
1102
  <div class="progress-track">
1103
  <div class="progress-fill" style="width: ${progressPct}%;"></div>
1104
  </div>
 
1107
  <span>約合 <b>${weeksLeft}</b> 週</span>
1108
  </div>
1109
  </div>
 
1110
 
1111
  <div class="card-badge-wrap">
1112
  <div class="status-capsule">${badgeText}</div>
 
1120
  });
1121
  }
1122
 
1123
+ // ========================================================
1124
+ // 大屏觸控與滑鼠拖曳/縮放核心 (修復卡頓:拖動中不摧毀 DOM)
1125
+ // ========================================================
1126
  function attachTouchAndPointerEvents(cardEl, cardData) {
1127
  const resizeHandle = cardEl.querySelector('.resize-handle');
1128
 
1129
+ // 1. 卡片移動拖曳
1130
  cardEl.addEventListener('pointerdown', (e) => {
1131
  if (!isEditing) return;
1132
  if (e.target === resizeHandle || e.target.classList.contains('resize-handle')) return;
 
1169
  cardEl.addEventListener('pointercancel', onPointerUp);
1170
  });
1171
 
1172
+ // 2. 右下角角標拉伸縮放 (流暢優化:即時修改樣式,放開才全面儲存)
1173
  resizeHandle.addEventListener('pointerdown', (e) => {
1174
  if (!isEditing) return;
1175
  e.stopPropagation();
 
1181
  let startW = cardEl.offsetWidth;
1182
  let startH = cardEl.offsetHeight;
1183
 
1184
+ const metricNum = cardEl.querySelector('.metric-number');
1185
+ const dynamicBody = cardEl.querySelector('.card-dynamic-body');
1186
+
1187
  function onResizeMove(ev) {
1188
  if (ev.pointerId !== e.pointerId) return;
1189
  ev.preventDefault();
1190
+
1191
+ // 直覺計算全新寬度與高度
1192
  const newW = Math.max(240, startW + (ev.clientX - startX));
1193
  const newH = Math.max(180, startH + (ev.clientY - startY));
1194
 
1195
+ // 直接操作當前卡片樣式,不中斷事件流
1196
  cardEl.style.width = `${newW}px`;
1197
  cardEl.style.height = `${newH}px`;
1198
  cardData.w = newW;
1199
  cardData.h = newH;
1200
+
1201
+ // 動態平滑調整大數字字級
1202
+ const isTall = newH >= 360;
1203
+ const fontScale = Math.min(newW / 4, newH / (isTall ? 3.8 : 2.5));
1204
+ const fontSizeRem = Math.max(2.8, Math.min(fontScale / 16, 7.5));
1205
+ if (metricNum) metricNum.style.fontSize = `${fontSizeRem}rem`;
1206
+
1207
+ // 動態顯示/隱藏進度條
1208
+ if (dynamicBody) dynamicBody.style.display = isTall ? 'flex' : 'none';
1209
  }
1210
 
1211
  function onResizeUp(ev) {
 
1214
  resizeHandle.removeEventListener('pointermove', onResizeMove);
1215
  resizeHandle.removeEventListener('pointerup', onResizeUp);
1216
  resizeHandle.removeEventListener('pointercancel', onResizeUp);
1217
+
1218
+ // 手指放開時,保存數據並重新校準極光焦點
1219
  saveAppData();
1220
+ renderBoard();
1221
  }
1222
 
1223
  resizeHandle.addEventListener('pointermove', onResizeMove);
 
1226
  });
1227
  }
1228
 
1229
+ // 極光引擎 (多重高亮焦點光暈)
1230
  const canvas = document.getElementById("aurora-canvas");
1231
  const ctx = canvas.getContext("2d");
1232
  let animId = null;
 
1243
  ctx.clearRect(0, 0, canvas.width, canvas.height);
1244
  step += 0.008;
1245
 
 
1246
  const highlightCards = appState.cards.filter(c => c.highlight);
1247
  const primaryHighlight = highlightCards[0];
1248
  const focalX = primaryHighlight ? (primaryHighlight.x + primaryHighlight.w / 2) : canvas.width * 0.7;
 
1287
  ctx.filter = "none";
1288
  });
1289
 
 
1290
  highlightCards.forEach(c => {
1291
  const cx = c.x + c.w / 2;
1292
  const cy = c.y + c.h / 2;
 
1406
  });
1407
  }
1408
 
 
1409
  function toggleCardHighlight(idx, isChecked) {
1410
  appState.cards[idx].highlight = isChecked;
1411
  renderBoard();