Optimize frontend rendering: delta updates, rAF debouncing, cached DOM refs

- Disable Chart.js animations on real-time FPS and perf charts
- Dashboard: delta-update profile badges on state changes instead of full DOM rebuild
- Dashboard: cache querySelector results in Map for metrics update loop
- Dashboard: debounce poll interval slider restart (300ms)
- Calibration: debounce ResizeObserver and span drag via requestAnimationFrame
- Calibration: batch updateCalibrationPreview canvas render into rAF

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 23:06:39 +03:00
parent fbf597dc29
commit 755077607a
3 changed files with 105 additions and 21 deletions

View File

@@ -45,6 +45,9 @@ class CalibrationModal extends Modal {
const calibModal = new CalibrationModal();
let _dragRaf = null;
let _previewRaf = null;
/* ── Public API (exported names unchanged) ────────────────────── */
export async function showCalibration(deviceId) {
@@ -117,8 +120,12 @@ export async function showCalibration(deviceId) {
if (!window._calibrationResizeObserver) {
window._calibrationResizeObserver = new ResizeObserver(() => {
updateSpanBars();
renderCalibrationCanvas();
if (window._calibrationResizeRaf) return;
window._calibrationResizeRaf = requestAnimationFrame(() => {
window._calibrationResizeRaf = null;
updateSpanBars();
renderCalibrationCanvas();
});
});
}
window._calibrationResizeObserver.observe(preview);
@@ -202,8 +209,12 @@ export function updateCalibrationPreview() {
if (toggleEl) toggleEl.classList.toggle('edge-disabled', count === 0);
});
updateSpanBars();
renderCalibrationCanvas();
if (_previewRaf) cancelAnimationFrame(_previewRaf);
_previewRaf = requestAnimationFrame(() => {
_previewRaf = null;
updateSpanBars();
renderCalibrationCanvas();
});
}
export function renderCalibrationCanvas() {
@@ -509,11 +520,19 @@ function initSpanDrag() {
if (handleType === 'start') span.start = Math.min(fraction, span.end - MIN_SPAN);
else span.end = Math.max(fraction, span.start + MIN_SPAN);
updateSpanBars();
renderCalibrationCanvas();
if (!_dragRaf) {
_dragRaf = requestAnimationFrame(() => {
_dragRaf = null;
updateSpanBars();
renderCalibrationCanvas();
});
}
}
function onMouseUp() {
if (_dragRaf) { cancelAnimationFrame(_dragRaf); _dragRaf = null; }
updateSpanBars();
renderCalibrationCanvas();
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
}
@@ -548,11 +567,19 @@ function initSpanDrag() {
span.start = newStart;
span.end = newStart + spanWidth;
updateSpanBars();
renderCalibrationCanvas();
if (!_dragRaf) {
_dragRaf = requestAnimationFrame(() => {
_dragRaf = null;
updateSpanBars();
renderCalibrationCanvas();
});
}
}
function onMouseUp() {
if (_dragRaf) { cancelAnimationFrame(_dragRaf); _dragRaf = null; }
updateSpanBars();
renderCalibrationCanvas();
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
}