mirror of
https://github.com/samsonjs/spirit-tracker.git
synced 2026-03-25 09:25:51 +00:00
UX Improvements
This commit is contained in:
parent
e91315557e
commit
d1cb5c9f7b
1 changed files with 46 additions and 29 deletions
|
|
@ -944,7 +944,14 @@ export async function renderItem($app, skuInput) {
|
||||||
const t = (storeMins[0].min + storeMins[1].min + storeMins[2].min) / 3;
|
const t = (storeMins[0].min + storeMins[1].min + storeMins[2].min) / 3;
|
||||||
if (Number.isFinite(t)) markers.push({ y: Math.round(t), text: "Target" });
|
if (Number.isFinite(t)) markers.push({ y: Math.round(t), text: "Target" });
|
||||||
}
|
}
|
||||||
|
const markerYs = markers.map(m => Number(m.y)).filter(Number.isFinite);
|
||||||
|
|
||||||
|
// helper: approximate font px size from a CSS font string (Chart uses one)
|
||||||
|
function fontPx(font) {
|
||||||
|
const m = String(font || "").match(/(\d+(?:\.\d+)?)px/);
|
||||||
|
return m ? Number(m[1]) : 12;
|
||||||
|
}
|
||||||
|
|
||||||
const ctx = $canvas.getContext("2d");
|
const ctx = $canvas.getContext("2d");
|
||||||
CHART = new Chart(ctx, {
|
CHART = new Chart(ctx, {
|
||||||
type: "line",
|
type: "line",
|
||||||
|
|
@ -993,37 +1000,47 @@ export async function renderItem($app, skuInput) {
|
||||||
x: { ticks: { maxRotation: 0, autoSkip: true, maxTicksLimit: 12 }, grid: { display: false } },
|
x: { ticks: { maxRotation: 0, autoSkip: true, maxTicksLimit: 12 }, grid: { display: false } },
|
||||||
y: {
|
y: {
|
||||||
...ySug,
|
...ySug,
|
||||||
|
ticks: {
|
||||||
y: {
|
stepSize: step,
|
||||||
...ySug,
|
maxTicksLimit: MAX_TICKS,
|
||||||
ticks: {
|
padding: 10,
|
||||||
stepSize: step,
|
callback: function (v) {
|
||||||
maxTicksLimit: MAX_TICKS,
|
const val = Number(v);
|
||||||
padding: 10,
|
if (!Number.isFinite(val)) return "";
|
||||||
callback: function (v) {
|
|
||||||
const val = Number(v);
|
|
||||||
if (!Number.isFinite(val)) return "";
|
|
||||||
|
|
||||||
// if no markers or scale API missing, just render normally
|
|
||||||
if (!markerYs.length || typeof this.getPixelForValue !== "function") {
|
|
||||||
return `$${val.toFixed(0)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const py = this.getPixelForValue(val);
|
|
||||||
if (!Number.isFinite(py)) return `$${val.toFixed(0)}`;
|
|
||||||
|
|
||||||
for (const my of markerYs) {
|
|
||||||
const pmy = this.getPixelForValue(my);
|
|
||||||
if (!Number.isFinite(pmy)) continue;
|
|
||||||
|
|
||||||
// only consider markers actually in view
|
|
||||||
if (pmy < this.top || pmy > this.bottom) continue;
|
|
||||||
|
|
||||||
if (Math.abs(py - pmy) <= HIDE_TICK_PX) return ""; // hide $ tick label
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// if no markers, normal label
|
||||||
|
if (!markerYs.length || typeof this.getPixelForValue !== "function") {
|
||||||
return `$${val.toFixed(0)}`;
|
return `$${val.toFixed(0)}`;
|
||||||
},
|
}
|
||||||
|
|
||||||
|
const py = this.getPixelForValue(val);
|
||||||
|
if (!Number.isFinite(py)) return `$${val.toFixed(0)}`;
|
||||||
|
|
||||||
|
// derive a "collision window" from tick label height
|
||||||
|
// Chart.js puts resolved font on ticks.font (v3+), otherwise fall back
|
||||||
|
const tickFont =
|
||||||
|
this?.options?.ticks?.font ||
|
||||||
|
this?.ctx?.font ||
|
||||||
|
"12px system-ui";
|
||||||
|
|
||||||
|
const h = fontPx(
|
||||||
|
typeof tickFont === "string"
|
||||||
|
? tickFont
|
||||||
|
: `${tickFont?.size || 12}px ${tickFont?.family || "system-ui"}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// hide if within 55% of label height (tweak 0.45–0.75)
|
||||||
|
const COLLIDE_PX = Math.max(6, h * 0.55);
|
||||||
|
|
||||||
|
for (const my of markerYs) {
|
||||||
|
const pmy = this.getPixelForValue(my);
|
||||||
|
if (!Number.isFinite(pmy)) continue;
|
||||||
|
if (pmy < this.top || pmy > this.bottom) continue;
|
||||||
|
|
||||||
|
if (Math.abs(py - pmy) <= COLLIDE_PX) return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return `$${val.toFixed(0)}`;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue