Add logarithmic scale, custom labels, and fixed-point number formatting
- New Linear/Log mapping toggle; log mode uses geometric major-tick values with log-positioned minor ticks (validates min/max > 0) - Optional comma-separated custom labels that override the calculated numbers and set the label count - Format numbers in fixed-point at 4 significant figures (no more scientific notation like "1e+04"), snapping log-scale FP drift to ints - Bump version to 0.75
This commit is contained in:
@@ -311,7 +311,16 @@
|
||||
|
||||
<div class="section">
|
||||
<div class="section-eye">Scale range</div>
|
||||
<div class="row row-2">
|
||||
<div class="row row-3">
|
||||
<div class="field">
|
||||
<label>Mapping</label>
|
||||
<div class="mode-toggle" role="group" aria-label="Scale mapping">
|
||||
<button type="button" class="mode-btn active" data-scale="linear"
|
||||
title="Values spaced evenly along the scale">Linear</button>
|
||||
<button type="button" class="mode-btn" data-scale="log"
|
||||
title="Values spaced logarithmically — requires min and max greater than 0">Log</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Min value</label>
|
||||
<input name="min" type="number" step="any" value="0" required>
|
||||
@@ -321,6 +330,7 @@
|
||||
<input name="max" type="number" step="any" value="100" required>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="scale_type" id="scale-type" value="linear">
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
@@ -340,6 +350,13 @@
|
||||
<span style="font-family:var(--f-mono);font-size:0.65rem;color:var(--muted)">(Labels minus one) should divide evenly into Major intervals for best appearance</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="margin-top:1.25rem">
|
||||
<div class="field">
|
||||
<label>Custom labels (optional)</label>
|
||||
<input name="labels" type="text" placeholder="e.g. Lo, 25, Mid, 75, Hi — leave blank to use calculated values">
|
||||
<span style="font-family:var(--f-mono);font-size:0.65rem;color:var(--muted)">Comma-separated. When set, overrides the calculated numbers and its count sets the number of labels.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
@@ -400,13 +417,26 @@
|
||||
text: 'Live text with embedded font — editable in SVG editors',
|
||||
};
|
||||
|
||||
document.querySelectorAll('.mode-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
document.querySelectorAll('.mode-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
document.getElementById('output-mode').value = btn.dataset.mode;
|
||||
document.getElementById('mode-desc').textContent = modeDesc[btn.dataset.mode];
|
||||
doGenerate();
|
||||
document.querySelectorAll('.mode-toggle').forEach(group => {
|
||||
group.querySelectorAll('.mode-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
group.querySelectorAll('.mode-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
if (btn.dataset.mode !== undefined) {
|
||||
document.getElementById('output-mode').value = btn.dataset.mode;
|
||||
document.getElementById('mode-desc').textContent = modeDesc[btn.dataset.mode];
|
||||
}
|
||||
if (btn.dataset.scale !== undefined) {
|
||||
document.getElementById('scale-type').value = btn.dataset.scale;
|
||||
if (btn.dataset.scale === 'log') {
|
||||
const minInput = document.querySelector('input[name="min"]');
|
||||
const maxInput = document.querySelector('input[name="max"]');
|
||||
if (!(parseFloat(minInput.value) > 0)) minInput.value = '1';
|
||||
if (!(parseFloat(maxInput.value) > 0)) maxInput.value = '100';
|
||||
}
|
||||
}
|
||||
doGenerate();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user