Improved cursors functionality
This commit is contained in:
@@ -225,6 +225,7 @@ function setActiveSig(plotId, key) {
|
||||
b.classList.toggle('sig-badge-active', key != null && b.dataset.key === key));
|
||||
const p = plots.find(q => q.id === plotId);
|
||||
if (p && p.uplot) p.uplot.redraw(false);
|
||||
updatePlotCursorReadouts();
|
||||
}
|
||||
|
||||
// Mark plots containing key dirty and refresh badge vscale text.
|
||||
@@ -1287,8 +1288,10 @@ function drawCursorLines(u, p) {
|
||||
ctx.fillText(label, px + 14, bbox.top + 2);
|
||||
// Per-trace: diamond at crossing point + value label
|
||||
if (p) {
|
||||
const DSZ = 5; // diamond half-size in px
|
||||
const activeKey = plotActiveSignal[p.id];
|
||||
p.traces.forEach((key, idx) => {
|
||||
const isActive = key === activeKey || (!activeKey && p.traces.length === 1);
|
||||
const DSZ = isActive ? 9 : 5; // diamond half-size in px
|
||||
const vNorm = interpAtTime(u, idx + 1, val);
|
||||
if (vNorm === null) return;
|
||||
const cy = u.valToPos(vNorm, 'y', true);
|
||||
@@ -2019,10 +2022,56 @@ document.getElementById('btn-cursor').addEventListener('click', () => {
|
||||
cursorsDirty = true;
|
||||
});
|
||||
|
||||
// Format a signal value for the per-plot cursor readout.
|
||||
function fmtVal(v) {
|
||||
if (v === null || v === undefined) return '—';
|
||||
return Math.abs(v) >= 10000 ? v.toExponential(2) : parseFloat(v.toPrecision(4)).toString();
|
||||
}
|
||||
|
||||
// Interpolate the real-unit value of the active/sole signal in plot p at time t.
|
||||
function getValueAtCursor(p, t) {
|
||||
if (!p.uplot || t === null) return null;
|
||||
const key = plotActiveSignal[p.id] || (p.traces.length === 1 ? p.traces[0] : null);
|
||||
if (!key) return null;
|
||||
const idx = p.traces.indexOf(key);
|
||||
if (idx < 0) return null;
|
||||
const vNorm = interpAtTime(p.uplot, idx + 1, t);
|
||||
if (vNorm === null) return null;
|
||||
// Un-normalize: y_norm = (y_raw - offset) / divValue + screenPos
|
||||
const vs = sigVScale[p.id + ':' + key];
|
||||
if (!vs) return vNorm;
|
||||
const dv = vs._resolvedDiv != null ? vs._resolvedDiv : (vs.divValue || 1);
|
||||
const ofs = vs._resolvedOffset != null ? vs._resolvedOffset : (vs.offset || 0);
|
||||
const sp = vs.screenPos || 0;
|
||||
return (vNorm - sp) * dv + ofs;
|
||||
}
|
||||
|
||||
// Update per-plot cursor value readouts (A, B, ΔV) for all plots.
|
||||
function updatePlotCursorReadouts() {
|
||||
plots.forEach(p => {
|
||||
const el = document.getElementById('pcur-' + p.id);
|
||||
if (!el) return;
|
||||
// Show only when cursors are on and the plot has an active or sole signal.
|
||||
const key = plotActiveSignal[p.id] || (p.traces.length === 1 ? p.traces[0] : null);
|
||||
if (cursors.mode !== 'on' || !key || !p.uplot) {
|
||||
el.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
const vA = getValueAtCursor(p, cursors.tA);
|
||||
const vB = getValueAtCursor(p, cursors.tB);
|
||||
const dv = (vA !== null && vB !== null) ? vB - vA : null;
|
||||
document.getElementById('pcur-a-' + p.id).textContent = 'A: ' + fmtVal(vA);
|
||||
document.getElementById('pcur-b-' + p.id).textContent = 'B: ' + fmtVal(vB);
|
||||
document.getElementById('pcur-dv-' + p.id).textContent = 'ΔV: ' + fmtVal(dv);
|
||||
el.style.display = 'flex';
|
||||
});
|
||||
}
|
||||
|
||||
function updateCursorReadout() {
|
||||
const ro = document.getElementById('cursor-readout');
|
||||
const active = cursors.mode === 'on';
|
||||
ro.classList.toggle('visible', active);
|
||||
updatePlotCursorReadouts();
|
||||
if (!active) return;
|
||||
|
||||
// Use the current visible x-range to pick the display unit.
|
||||
@@ -2605,6 +2654,13 @@ function addPlot() {
|
||||
<div class="plot-card-header">
|
||||
<span class="plot-title" id="ptitle-${id}" title="Click to configure">Plot ${id}</span>
|
||||
<div class="sig-badges" id="badges-${id}"></div>
|
||||
<div class="plot-cursor-ro" id="pcur-${id}" style="display:none">
|
||||
<span class="pcur-a" id="pcur-a-${id}">A: —</span>
|
||||
<span class="pcur-sep">│</span>
|
||||
<span class="pcur-b" id="pcur-b-${id}">B: —</span>
|
||||
<span class="pcur-sep">│</span>
|
||||
<span class="pcur-dv" id="pcur-dv-${id}">ΔV: —</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="plot-cfg-bar" id="pcfg-${id}" style="display:none">
|
||||
<div class="vstb-header">
|
||||
@@ -2657,6 +2713,7 @@ function addTraceTo(plotId, signalKey) {
|
||||
// Recreate uPlot with new series list
|
||||
createUPlot(p);
|
||||
p.needsRedraw = true;
|
||||
updatePlotCursorReadouts();
|
||||
}
|
||||
|
||||
function removeTraceFrom(plotId, signalKey) {
|
||||
@@ -2672,6 +2729,7 @@ function removeTraceFrom(plotId, signalKey) {
|
||||
createUPlot(p);
|
||||
p.needsRedraw = true;
|
||||
if (!p.traces.length) document.querySelector('#hint-' + plotId).style.display = '';
|
||||
updatePlotCursorReadouts();
|
||||
}
|
||||
|
||||
function addBadge(plotId, key) {
|
||||
@@ -2843,6 +2901,9 @@ function renderDirtyPlots() {
|
||||
zoomGuard = false;
|
||||
});
|
||||
|
||||
// Keep per-plot cursor value readouts in sync with live data.
|
||||
if (cursors.mode === 'on') updatePlotCursorReadouts();
|
||||
|
||||
requestAnimationFrame(renderDirtyPlots);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user