Spaces:
Running
Running
Upload 8 files
Browse files- src/views/InstructorView.js +18 -14
src/views/InstructorView.js
CHANGED
|
@@ -2,9 +2,9 @@ import { createRoom, subscribeToRoom, getChallenges, resetProgress } from "../se
|
|
| 2 |
|
| 3 |
import { generateMonsterSVG, getNextMonster } from "../utils/monsterUtils.js";
|
| 4 |
|
| 5 |
-
// Load
|
| 6 |
const script = document.createElement('script');
|
| 7 |
-
script.src = "https://
|
| 8 |
document.head.appendChild(script);
|
| 9 |
|
| 10 |
let cachedChallenges = [];
|
|
@@ -203,7 +203,10 @@ export function setupInstructorEvents() {
|
|
| 203 |
|
| 204 |
// Snapshot Logic
|
| 205 |
snapshotBtn.addEventListener('click', async () => {
|
| 206 |
-
if (isSnapshotting || typeof
|
|
|
|
|
|
|
|
|
|
| 207 |
isSnapshotting = true;
|
| 208 |
|
| 209 |
const overlay = document.getElementById('snapshot-overlay');
|
|
@@ -251,15 +254,16 @@ export function setupInstructorEvents() {
|
|
| 251 |
const emoji = emojis[Math.floor(Math.random() * emojis.length)];
|
| 252 |
const emojiEl = document.createElement('div');
|
| 253 |
emojiEl.textContent = emoji;
|
| 254 |
-
|
| 255 |
-
emojiEl.
|
|
|
|
| 256 |
card.appendChild(emojiEl);
|
| 257 |
|
| 258 |
-
// Remove after
|
| 259 |
setTimeout(() => emojiEl.remove(), 3000);
|
| 260 |
});
|
| 261 |
|
| 262 |
-
// 2. Capture
|
| 263 |
setTimeout(async () => {
|
| 264 |
try {
|
| 265 |
// Flash Effect
|
|
@@ -269,23 +273,23 @@ export function setupInstructorEvents() {
|
|
| 269 |
setTimeout(() => flash.style.opacity = '0', 50);
|
| 270 |
setTimeout(() => flash.remove(), 300);
|
| 271 |
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
});
|
| 278 |
|
| 279 |
// Download
|
| 280 |
const link = document.createElement('a');
|
| 281 |
const dateStr = new Date().toISOString().slice(0, 10);
|
| 282 |
link.download = `VIBE_Class_Photo_${dateStr}.png`;
|
| 283 |
-
link.href =
|
| 284 |
link.click();
|
| 285 |
|
| 286 |
} catch (e) {
|
| 287 |
console.error("Snapshot failed:", e);
|
| 288 |
-
alert("截圖失敗
|
| 289 |
} finally {
|
| 290 |
// Restore UI
|
| 291 |
if (closeBtn) closeBtn.style.opacity = '1';
|
|
|
|
| 2 |
|
| 3 |
import { generateMonsterSVG, getNextMonster } from "../utils/monsterUtils.js";
|
| 4 |
|
| 5 |
+
// Load html-to-image dynamically (Better support than html2canvas)
|
| 6 |
const script = document.createElement('script');
|
| 7 |
+
script.src = "https://cdnjs.cloudflare.com/ajax/libs/html-to-image/1.11.11/html-to-image.js";
|
| 8 |
document.head.appendChild(script);
|
| 9 |
|
| 10 |
let cachedChallenges = [];
|
|
|
|
| 203 |
|
| 204 |
// Snapshot Logic
|
| 205 |
snapshotBtn.addEventListener('click', async () => {
|
| 206 |
+
if (isSnapshotting || typeof htmlToImage === 'undefined') {
|
| 207 |
+
if (typeof htmlToImage === 'undefined') alert("截圖元件尚未載入,請稍候再試");
|
| 208 |
+
return;
|
| 209 |
+
}
|
| 210 |
isSnapshotting = true;
|
| 211 |
|
| 212 |
const overlay = document.getElementById('snapshot-overlay');
|
|
|
|
| 254 |
const emoji = emojis[Math.floor(Math.random() * emojis.length)];
|
| 255 |
const emojiEl = document.createElement('div');
|
| 256 |
emojiEl.textContent = emoji;
|
| 257 |
+
// Updated Position: Top-Right, Smaller, Overlapping
|
| 258 |
+
emojiEl.className = 'absolute -top-3 -right-3 text-2xl animate-bounce z-50 drop-shadow-md';
|
| 259 |
+
emojiEl.style.animationDuration = '0.6s';
|
| 260 |
card.appendChild(emojiEl);
|
| 261 |
|
| 262 |
+
// Remove after 3s
|
| 263 |
setTimeout(() => emojiEl.remove(), 3000);
|
| 264 |
});
|
| 265 |
|
| 266 |
+
// 2. Capture using html-to-image
|
| 267 |
setTimeout(async () => {
|
| 268 |
try {
|
| 269 |
// Flash Effect
|
|
|
|
| 273 |
setTimeout(() => flash.style.opacity = '0', 50);
|
| 274 |
setTimeout(() => flash.remove(), 300);
|
| 275 |
|
| 276 |
+
// Use htmlToImage.toPng
|
| 277 |
+
const dataUrl = await htmlToImage.toPng(container, {
|
| 278 |
+
backgroundColor: '#111827',
|
| 279 |
+
pixelRatio: 2,
|
| 280 |
+
cacheBust: true,
|
| 281 |
});
|
| 282 |
|
| 283 |
// Download
|
| 284 |
const link = document.createElement('a');
|
| 285 |
const dateStr = new Date().toISOString().slice(0, 10);
|
| 286 |
link.download = `VIBE_Class_Photo_${dateStr}.png`;
|
| 287 |
+
link.href = dataUrl;
|
| 288 |
link.click();
|
| 289 |
|
| 290 |
} catch (e) {
|
| 291 |
console.error("Snapshot failed:", e);
|
| 292 |
+
alert("截圖失敗 (請嘗試手動截圖/PrtSc)\n原因: " + e.message);
|
| 293 |
} finally {
|
| 294 |
// Restore UI
|
| 295 |
if (closeBtn) closeBtn.style.opacity = '1';
|