Мінікарта: шрифт 6 px і вирівнювання по піксельній сітці
All checks were successful
CI / hygiene (push) Successful in 11s
CI / web (push) Successful in 1m7s
CI / server (push) Successful in 1m36s
CI / agent (push) Successful in 58s

Менше — на прохання. Чіткіше — виправленням того, чого бракувало з
самого початку: полотно масштабоване на dpr, тож координата 9 при
масштабі 1.25 дає 11.25 фізичного пікселя, і браузер розмазує літеру
між двома. На дрібному шрифті це читається як «нечітко», хоча винен не
розмір, а півпікселя зсуву.

Тепер позиції округлюються до цілого пристроєвого пікселя. Розмиття
зникає без жодної втрати, і саме тому шість пікселів тепер працюють
там, де раніше не вистачало семи.
This commit is contained in:
byrsapty 2026-08-27 23:23:35 +03:00
parent 68fd47ff19
commit 45869f2dce

View file

@ -79,22 +79,23 @@ export const MAP_W = 180
* Розмін свідомий: мініатюра, на якій нічого не розібрати, не стає * Розмін свідомий: мініатюра, на якій нічого не розібрати, не стає
* кориснішою від того, що вміщає більше. * кориснішою від того, що вміщає більше.
*/ */
const ROW_PX = 8 const ROW_PX = 7
/** /**
* Розмір шрифту мініатюри. * Розмір шрифту мініатюри.
* *
* Сім пікселів найменше, на чому моноширинний шрифт ще лишається * Шість, а не сім. На сімці літери читались, але займали більше місця,
* ЛІТЕРАМИ, а не сірою крупою. Менше пробували: на шести зникають * ніж треба: мініатюра має показувати ДЕ ти в файлі, а не пропонувати
* внутрішні просвіти в «e», «a», «o», і слово перетворюється на пляму * себе замість тексту поруч.
* тієї самої довжини.
* *
* Звідси й ROW_PX = 8: сім на літери, один на просвіт між рядками. * Чіткість на шести тримається не розміром, а вирівнюванням по
* Рядків у вікні стає близько вісімдесяти замість двохсот і це не * піксельній сітці (див. snap нижче). Без нього шрифт цього розміру
* втрата, а обмін. Двісті нечитабельних рядків показують силует файла; * розмазується на дробовому масштабі екрана і саме розмиття, а не
* вісімдесят читабельних показують, ДЕ ти в ньому. Друге і просили. * розмір, читається як «нечітко».
*
* ROW_PX = 7: шість на літери, один на просвіт між рядками.
*/ */
const FONT_PX = 7 const FONT_PX = 6
/** /**
* Товщина штриха рядка. Один піксель, а не два і це не косметика. * Товщина штриха рядка. Один піксель, а не два і це не косметика.
@ -398,6 +399,15 @@ export function Minimap({
// а хвіст із адресами й масками не читався б однаково. // а хвіст із адресами й масками не читався б однаково.
ctx.font = FONT_PX + 'px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace' ctx.font = FONT_PX + 'px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace'
ctx.textBaseline = 'top' ctx.textBaseline = 'top'
// Вирівнювання по піксельній сітці ПРИСТРОЮ, а не CSS.
//
// Полотно масштабоване на dpr, тож координата 9 при dpr 1.25 дає
// 11.25 фізичного пікселя — і браузер розмазує літеру між двома.
// На дрібному шрифті це видно як «нечітко»: розмір тут ні до чого,
// винне півпікселя зсуву. Округлення до цілого пристроєвого
// пікселя прибирає розмиття без жодної втрати.
const snap = (v: number) => Math.round(v * dpr) / dpr
// Ширину символа беремо вимірюванням, а не формулою: у різних // Ширину символа беремо вимірюванням, а не формулою: у різних
// системах підставляється різний моноширинний шрифт, і константа // системах підставляється різний моноширинний шрифт, і константа
// тут рано чи пізно розійшлася б із дійсністю мовчки. // тут рано чи пізно розійшлася б із дійсністю мовчки.
@ -442,7 +452,7 @@ export function Minimap({
// блоки JunOS з'їхали б до лівого краю й структура зникла саме // блоки JunOS з'їхали б до лівого краю й структура зникла саме
// там, де вона найпомітніша. // там, де вона найпомітніша.
const flat = text.length > maxChars * 2 ? text.slice(0, maxChars * 2) : text const flat = text.length > maxChars * 2 ? text.slice(0, maxChars * 2) : text
ctx.fillText(flat.replace(/ /g, ' ').slice(0, maxChars), left, y) ctx.fillText(flat.replace(/ /g, ' ').slice(0, maxChars), snap(left), snap(y))
} }
if (fits) { if (fits) {