SPL Meter: measure the room, not just watch it #10
@@ -196,6 +196,38 @@ function readoutView(root, moduleApi) {
|
||||
const unit = root.querySelector('.spl-unit');
|
||||
const sub = root.querySelector('.spl-sub');
|
||||
const box = root.querySelector('.spl-readout');
|
||||
const value = root.querySelector('.spl-value');
|
||||
let fitKey = '';
|
||||
|
||||
/**
|
||||
* Grow the number until it fills the tile, measuring the text we actually
|
||||
* have rather than assuming a digit count.
|
||||
*
|
||||
* The CSS can only guess at width — it has to pick a cqw coefficient for
|
||||
* some number of characters, and then "-100.5" overflows the tile that
|
||||
* "-45.9" merely filled. Measuring costs one layout read, and only when
|
||||
* the tile size or the length of the reading changes.
|
||||
*/
|
||||
function fit() {
|
||||
const w = root.clientWidth, h = root.clientHeight;
|
||||
const key = `${w}x${h}:${num.textContent.length}:${unit.textContent}`;
|
||||
if (key === fitKey || w < 2 || h < 2) return;
|
||||
fitKey = key;
|
||||
|
||||
const TRIAL = 100;
|
||||
num.style.fontSize = `${TRIAL}px`;
|
||||
unit.style.fontSize = `${TRIAL * 0.26}px`;
|
||||
const natural = value.scrollWidth || 1;
|
||||
|
||||
// Leave the caption its room when it is showing, and a little air either
|
||||
// way so descenders and the tile's padding never clip.
|
||||
const subH = sub.offsetParent ? sub.getBoundingClientRect().height + 6 : 0;
|
||||
const byHeight = (h - subH) * 0.92;
|
||||
const byWidth = ((w - 8) * TRIAL) / natural;
|
||||
const size = Math.max(12, Math.min(byHeight, byWidth));
|
||||
num.style.fontSize = `${size}px`;
|
||||
unit.style.fontSize = `${size * 0.26}px`;
|
||||
}
|
||||
|
||||
return {
|
||||
render(payload) {
|
||||
@@ -205,6 +237,7 @@ function readoutView(root, moduleApi) {
|
||||
num.textContent = '––.–';
|
||||
sub.textContent = payload && payload.error ? payload.error : '';
|
||||
box.dataset.level = 'idle';
|
||||
fit();
|
||||
return;
|
||||
}
|
||||
const value = readValue(ch, s);
|
||||
@@ -225,8 +258,9 @@ function readoutView(root, moduleApi) {
|
||||
if (ch.clip) parts.push('CLIP');
|
||||
if (!payload.calibrated) parts.push('uncalibrated');
|
||||
sub.textContent = parts.join(' · ');
|
||||
fit();
|
||||
},
|
||||
resize() {},
|
||||
resize() { fitKey = ''; fit(); },
|
||||
destroy() { root.innerHTML = ''; },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "spl-meter",
|
||||
"name": "SPL Meter",
|
||||
"version": "0.2.0",
|
||||
"version": "0.2.1",
|
||||
"proddash": ">=1.5.0",
|
||||
"description": "Calibrated sound level, Leq and RTA from an audio input on this machine",
|
||||
"permissions": [
|
||||
|
||||
@@ -30,18 +30,19 @@
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
/* Sized off the tile, so one cell and six cells both read well. Height has
|
||||
to be in the min() as well as width: a 2x1 tile is wide and short, and
|
||||
sizing on width alone pushes the digits straight out through the top. */
|
||||
/* A first-paint size only. client.js measures the text and sets the real
|
||||
one inline, because CSS has to assume a digit count and gets it wrong the
|
||||
moment the reading needs a sixth character: the coefficient that fills a
|
||||
tile for "-45.9" pushes "-100.5" straight out through the side. */
|
||||
[data-module="spl-meter"] .spl-num {
|
||||
font-size: clamp(1.25rem, min(20cqw, 42cqh), 6rem);
|
||||
font-size: clamp(1.25rem, min(26cqw, 60cqh), 100rem);
|
||||
font-variant-numeric: tabular-nums;
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
[data-module="spl-meter"] .spl-unit {
|
||||
font-size: clamp(0.65rem, min(6cqw, 13cqh), 1.5rem);
|
||||
font-size: clamp(0.65rem, min(7cqw, 15cqh), 26rem);
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user