Spaces:
Running
Running
Upload 8 files
Browse files- src/views/InstructorView.js +63 -10
src/views/InstructorView.js
CHANGED
|
@@ -140,18 +140,36 @@ export async function renderInstructorView() {
|
|
| 140 |
👀 隱藏姓名
|
| 141 |
</button>
|
| 142 |
<!-- Pen Tools -->
|
| 143 |
-
<button class="annotation-tool p-2 rounded-full hover:bg-gray-700 transition-colors ring-2
|
| 144 |
<div class="w-4 h-4 rounded-full bg-red-500"></div>
|
| 145 |
</button>
|
| 146 |
-
<button class="annotation-tool p-2 rounded-full hover:bg-gray-700 transition-colors ring-2 ring-transparent focus:outline-none" data-color="#3b82f6" onclick="
|
| 147 |
<div class="w-4 h-4 rounded-full bg-blue-500"></div>
|
| 148 |
</button>
|
| 149 |
-
<button class="annotation-tool p-2 rounded-full hover:bg-gray-700 transition-colors ring-2 ring-transparent focus:outline-none" data-color="#
|
| 150 |
<div class="w-4 h-4 rounded-full bg-yellow-500"></div>
|
| 151 |
</button>
|
|
|
|
| 152 |
<div class="w-px h-6 bg-gray-600 mx-2"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 153 |
<button onclick="clearCanvas()" class="text-gray-400 hover:text-white text-sm font-bold px-2">
|
| 154 |
-
清除
|
| 155 |
</button>
|
| 156 |
</div>
|
| 157 |
|
|
@@ -1135,10 +1153,12 @@ ${item.prompt}
|
|
| 1135 |
clearCanvas();
|
| 1136 |
};
|
| 1137 |
|
| 1138 |
-
// --- Phase 3: Annotation Tools ---
|
| 1139 |
let canvas, ctx;
|
| 1140 |
let isDrawing = false;
|
| 1141 |
let currentPenColor = '#ef4444'; // Red default
|
|
|
|
|
|
|
| 1142 |
|
| 1143 |
window.setupCanvas = () => {
|
| 1144 |
canvas = document.getElementById('annotation-canvas');
|
|
@@ -1154,15 +1174,25 @@ ${item.prompt}
|
|
| 1154 |
ctx.lineCap = 'round';
|
| 1155 |
ctx.lineJoin = 'round';
|
| 1156 |
ctx.strokeStyle = currentPenColor;
|
| 1157 |
-
ctx.lineWidth =
|
|
|
|
| 1158 |
};
|
| 1159 |
resize();
|
| 1160 |
window.addEventListener('resize', resize);
|
| 1161 |
|
|
|
|
|
|
|
|
|
|
| 1162 |
// Drawing Events
|
| 1163 |
const start = (e) => {
|
| 1164 |
isDrawing = true;
|
| 1165 |
ctx.beginPath();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1166 |
const { x, y } = getPos(e);
|
| 1167 |
ctx.moveTo(x, y);
|
| 1168 |
};
|
|
@@ -1197,10 +1227,8 @@ ${item.prompt}
|
|
| 1197 |
};
|
| 1198 |
}
|
| 1199 |
|
| 1200 |
-
|
| 1201 |
-
|
| 1202 |
-
if (ctx) ctx.strokeStyle = color;
|
| 1203 |
-
|
| 1204 |
// UI Update
|
| 1205 |
document.querySelectorAll('.annotation-tool').forEach(b => {
|
| 1206 |
b.classList.remove('ring-white');
|
|
@@ -1208,8 +1236,33 @@ ${item.prompt}
|
|
| 1208 |
});
|
| 1209 |
btn.classList.remove('ring-transparent');
|
| 1210 |
btn.classList.add('ring-white');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1211 |
};
|
| 1212 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1213 |
window.clearCanvas = () => {
|
| 1214 |
if (canvas && ctx) {
|
| 1215 |
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
| 140 |
👀 隱藏姓名
|
| 141 |
</button>
|
| 142 |
<!-- Pen Tools -->
|
| 143 |
+
<button class="annotation-tool ring-white p-2 rounded-full hover:bg-gray-700 transition-colors ring-2 focus:outline-none" data-tool="pen" data-color="#ef4444" onclick="setPenTool('pen', '#ef4444', this)">
|
| 144 |
<div class="w-4 h-4 rounded-full bg-red-500"></div>
|
| 145 |
</button>
|
| 146 |
+
<button class="annotation-tool p-2 rounded-full hover:bg-gray-700 transition-colors ring-2 ring-transparent focus:outline-none" data-tool="pen" data-color="#3b82f6" onclick="setPenTool('pen', '#3b82f6', this)">
|
| 147 |
<div class="w-4 h-4 rounded-full bg-blue-500"></div>
|
| 148 |
</button>
|
| 149 |
+
<button class="annotation-tool p-2 rounded-full hover:bg-gray-700 transition-colors ring-2 ring-transparent focus:outline-none" data-tool="pen" data-color="#eab308" onclick="setPenTool('pen', '#eab308', this)">
|
| 150 |
<div class="w-4 h-4 rounded-full bg-yellow-500"></div>
|
| 151 |
</button>
|
| 152 |
+
|
| 153 |
<div class="w-px h-6 bg-gray-600 mx-2"></div>
|
| 154 |
+
|
| 155 |
+
<!-- Eraser -->
|
| 156 |
+
<button class="annotation-tool p-2 rounded-full hover:bg-gray-700 transition-colors ring-2 ring-transparent focus:outline-none" data-tool="eraser" onclick="setPenTool('eraser', null, this)" title="橡皮擦">
|
| 157 |
+
<span class="text-sm">🧽</span>
|
| 158 |
+
</button>
|
| 159 |
+
|
| 160 |
+
<div class="w-px h-6 bg-gray-600 mx-2"></div>
|
| 161 |
+
|
| 162 |
+
<!-- Size Selector -->
|
| 163 |
+
<div class="flex items-center space-x-1 bg-gray-800 rounded p-0.5">
|
| 164 |
+
<button class="size-btn px-2 py-0.5 text-xs text-gray-400 hover:text-white rounded hover:bg-gray-700" onclick="setPenSize(3, this)" data-size="3">S</button>
|
| 165 |
+
<button class="size-btn px-2 py-0.5 text-xs text-gray-400 hover:text-white rounded hover:bg-gray-700" onclick="setPenSize(8, this)" data-size="8">M</button>
|
| 166 |
+
<button class="size-btn px-2 py-0.5 text-xs text-gray-400 hover:text-white rounded hover:bg-gray-700" onclick="setPenSize(16, this)" data-size="16">L</button>
|
| 167 |
+
</div>
|
| 168 |
+
|
| 169 |
+
<div class="w-px h-6 bg-gray-600 mx-2"></div>
|
| 170 |
+
|
| 171 |
<button onclick="clearCanvas()" class="text-gray-400 hover:text-white text-sm font-bold px-2">
|
| 172 |
+
清除
|
| 173 |
</button>
|
| 174 |
</div>
|
| 175 |
|
|
|
|
| 1153 |
clearCanvas();
|
| 1154 |
};
|
| 1155 |
|
| 1156 |
+
// --- Phase 3 & 6: Annotation Tools ---
|
| 1157 |
let canvas, ctx;
|
| 1158 |
let isDrawing = false;
|
| 1159 |
let currentPenColor = '#ef4444'; // Red default
|
| 1160 |
+
let currentLineWidth = 3;
|
| 1161 |
+
let currentMode = 'source-over'; // 'source-over' (Pen) or 'destination-out' (Eraser)
|
| 1162 |
|
| 1163 |
window.setupCanvas = () => {
|
| 1164 |
canvas = document.getElementById('annotation-canvas');
|
|
|
|
| 1174 |
ctx.lineCap = 'round';
|
| 1175 |
ctx.lineJoin = 'round';
|
| 1176 |
ctx.strokeStyle = currentPenColor;
|
| 1177 |
+
ctx.lineWidth = currentLineWidth;
|
| 1178 |
+
ctx.globalCompositeOperation = currentMode;
|
| 1179 |
};
|
| 1180 |
resize();
|
| 1181 |
window.addEventListener('resize', resize);
|
| 1182 |
|
| 1183 |
+
// Init Size UI
|
| 1184 |
+
updateSizeBtnUI();
|
| 1185 |
+
|
| 1186 |
// Drawing Events
|
| 1187 |
const start = (e) => {
|
| 1188 |
isDrawing = true;
|
| 1189 |
ctx.beginPath();
|
| 1190 |
+
|
| 1191 |
+
// Re-apply settings (state might change)
|
| 1192 |
+
ctx.globalCompositeOperation = currentMode;
|
| 1193 |
+
ctx.strokeStyle = currentPenColor;
|
| 1194 |
+
ctx.lineWidth = currentLineWidth;
|
| 1195 |
+
|
| 1196 |
const { x, y } = getPos(e);
|
| 1197 |
ctx.moveTo(x, y);
|
| 1198 |
};
|
|
|
|
| 1227 |
};
|
| 1228 |
}
|
| 1229 |
|
| 1230 |
+
// Unified Tool Handler
|
| 1231 |
+
window.setPenTool = (tool, color, btn) => {
|
|
|
|
|
|
|
| 1232 |
// UI Update
|
| 1233 |
document.querySelectorAll('.annotation-tool').forEach(b => {
|
| 1234 |
b.classList.remove('ring-white');
|
|
|
|
| 1236 |
});
|
| 1237 |
btn.classList.remove('ring-transparent');
|
| 1238 |
btn.classList.add('ring-white');
|
| 1239 |
+
|
| 1240 |
+
if (tool === 'eraser') {
|
| 1241 |
+
currentMode = 'destination-out';
|
| 1242 |
+
} else {
|
| 1243 |
+
currentMode = 'source-over';
|
| 1244 |
+
currentPenColor = color;
|
| 1245 |
+
}
|
| 1246 |
+
};
|
| 1247 |
+
|
| 1248 |
+
// Size Handler
|
| 1249 |
+
window.setPenSize = (size, btn) => {
|
| 1250 |
+
currentLineWidth = size;
|
| 1251 |
+
updateSizeBtnUI();
|
| 1252 |
};
|
| 1253 |
|
| 1254 |
+
function updateSizeBtnUI() {
|
| 1255 |
+
document.querySelectorAll('.size-btn').forEach(b => {
|
| 1256 |
+
if (parseInt(b.dataset.size) === currentLineWidth) {
|
| 1257 |
+
b.classList.add('bg-gray-600', 'text-white');
|
| 1258 |
+
b.classList.remove('text-gray-400', 'hover:bg-gray-700');
|
| 1259 |
+
} else {
|
| 1260 |
+
b.classList.remove('bg-gray-600', 'text-white');
|
| 1261 |
+
b.classList.add('text-gray-400', 'hover:bg-gray-700');
|
| 1262 |
+
}
|
| 1263 |
+
});
|
| 1264 |
+
}
|
| 1265 |
+
|
| 1266 |
window.clearCanvas = () => {
|
| 1267 |
if (canvas && ctx) {
|
| 1268 |
ctx.clearRect(0, 0, canvas.width, canvas.height);
|