diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/api/dashboard/dashboard.html | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/src/api/dashboard/dashboard.html b/src/api/dashboard/dashboard.html index 086c03f..b586834 100644 --- a/src/api/dashboard/dashboard.html +++ b/src/api/dashboard/dashboard.html @@ -214,6 +214,11 @@ drop-shadow(-2px 0 0 var(--panel)) drop-shadow(0 2px 0 var(--panel)) drop-shadow(0 -2px 0 var(--panel)); } .map-overlay button, .map-overlay input, .map-overlay label { pointer-events: auto; } + /* How hard links pull, beside the layout's toggle while dynamic, as tall. */ + .map-controls .slider { display: inline-flex; align-items: center; gap: 4px; + font-size: 12px; color: var(--muted); height: 1.4em; } + .map-controls .slider[hidden] { display: none; } + .map-controls .slider input { width: 6em; height: 1em; margin: 0; } /* Hides the legend, and shows it again. */ button.toggle { font: inherit; font-size: 12px; text-transform: none; letter-spacing: 0; float: right; margin-left: 6px; padding: 0 6px; color: var(--muted); background: none; @@ -330,6 +335,9 @@ <div class="map-area"> <div class="map-overlay"> <div class="map-controls"> + <label id="pull" class="slider" hidden + title="How hard the links pull their ends together, against the nodes pushing each other apart">pull + <input id="pull-slider" type="range" min="-2" max="2" step=".25"></label> <button id="rtt-toggle" class="toggle">layout: static</button> <button id="tree-toggle" class="toggle">tree: off</button> <button id="legend-toggle" class="toggle">hide legend</button> @@ -1011,6 +1019,11 @@ function idealLength(count, width, height) { // `idealLength`), and whether it is loose (`lengths`). // How hard a loose link pulls, against a measured one. const LOOSE = .1; +// How hard links pull on a dynamic map, times what they do on a static one: 2 to the +// `pull` slider's value (ΒΌ to 4; 1 at first), kept in this browser. +let pullStrength = 1; +try { pullStrength = 2 ** (Number(localStorage.getItem("continuum-pull")) || 0); } catch (_) {} +pullStrength = Math.min(4, Math.max(.25, pullStrength)); // `only`, if given: the nodes laid out; the others stay where they are. function layout(nodes, pairs, width, height, only) { for (const id of nodes) { @@ -1053,8 +1066,10 @@ function relax(nodes, pairs, width, height, gain, most, only, placing) { if (!p || !q) continue; const dx = q.x - p.x, dy = q.y - p.y, d = Math.max(Math.hypot(dx, dy), 1); const stretch = d - (length || ideal); - // A loose link pulls a little, and never pushes. - const pull = loose ? Math.max(0, stretch) / d / 4 * LOOSE : stretch / d / 4; + // A loose link pulls a little, and never pushes; on a dynamic map, as hard as the + // slider says. + const strength = byRtt ? pullStrength : 1; + const pull = (loose ? Math.max(0, stretch) / d / 4 * LOOSE : stretch / d / 4) * strength; force.get(a).x += dx * pull; force.get(a).y += dy * pull; force.get(b).x -= dx * pull; force.get(b).y -= dy * pull; } @@ -2030,10 +2045,19 @@ treeToggle.addEventListener("click", () => { }); // Links as long as their round trips, and back. const rttToggle = document.getElementById("rtt-toggle"); +const pullSlider = document.getElementById("pull-slider"); +pullSlider.value = String(Math.log2(pullStrength)); +pullSlider.addEventListener("input", () => { + pullStrength = 2 ** Number(pullSlider.value); + try { localStorage.setItem("continuum-pull", pullSlider.value); } catch (_) {} + // Moved to the new balance, smoothly (`settle`). + if (state && byRtt && settleTo) settle(); +}); function showRttToggle() { rttToggle.textContent = byRtt ? "layout: dynamic" : "layout: static"; rttToggle.title = "Click for " + (byRtt ? "a static layout" : "a dynamic one: links as long as their round trips"); + document.getElementById("pull").hidden = !byRtt; } showRttToggle(); rttToggle.addEventListener("click", () => { |
