(width, height)
| 255 | } |
| 256 | |
| 257 | drawTrackMode(width, height) { |
| 258 | const ctx = this.ctx; |
| 259 | const tracking = this.data.tracking; |
| 260 | |
| 261 | if (!tracking) return; |
| 262 | |
| 263 | // 绘制追踪多边形 |
| 264 | if (tracking.polygon && tracking.polygon.length > 0) { |
| 265 | ctx.beginPath(); |
| 266 | ctx.strokeStyle = this.colors.accent; |
| 267 | ctx.lineWidth = 3; |
| 268 | ctx.shadowColor = this.colors.accent; |
| 269 | ctx.shadowBlur = 15; |
| 270 | |
| 271 | const points = this.scalePoints(tracking.polygon, width, height); |
| 272 | ctx.moveTo(points[0][0], points[0][1]); |
| 273 | points.forEach(p => ctx.lineTo(p[0], p[1])); |
| 274 | ctx.closePath(); |
| 275 | ctx.stroke(); |
| 276 | |
| 277 | ctx.shadowBlur = 0; |
| 278 | |
| 279 | // 绘制中心点 |
| 280 | if (tracking.center) { |
| 281 | const center = this.scalePoint(tracking.center, width, height); |
| 282 | ctx.fillStyle = this.colors.accent; |
| 283 | ctx.beginPath(); |
| 284 | ctx.arc(center[0], center[1], 6, 0, Math.PI * 2); |
| 285 | ctx.fill(); |
| 286 | } |
| 287 | } |
| 288 | |
| 289 | // 绘制进度条 |
| 290 | this.drawProgressBars(tracking, width, height); |
| 291 | |
| 292 | // 绘制引导文字 |
| 293 | if (tracking.guidance) { |
| 294 | const guidanceText = { |
| 295 | '向前靠近': 'Move Closer', |
| 296 | '后退': 'Move Back', |
| 297 | '保持': 'Hold Position' |
| 298 | }; |
| 299 | |
| 300 | this.drawStatusText( |
| 301 | tracking.guidance, |
| 302 | guidanceText[tracking.guidance] || '', |
| 303 | width / 2, |
| 304 | height - 100, |
| 305 | this.colors.warning |
| 306 | ); |
| 307 | } |
| 308 | |
| 309 | // 如果触发了重新锁定 |
| 310 | if (tracking.relock_triggered) { |
| 311 | this.drawStatusText( |
| 312 | '已根据周边检测刷新追踪', |
| 313 | 'Tracking refreshed by peripheral detection', |
| 314 | width / 2, |
no test coverage detected