From 45869f2dce7caed0a555dc4ef1845802e89ee70a Mon Sep 17 00:00:00 2001 From: byrsapty Date: Thu, 27 Aug 2026 23:23:35 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9C=D1=96=D0=BD=D1=96=D0=BA=D0=B0=D1=80?= =?UTF-8?q?=D1=82=D0=B0:=20=D1=88=D1=80=D0=B8=D1=84=D1=82=206=20px=20?= =?UTF-8?q?=D1=96=20=D0=B2=D0=B8=D1=80=D1=96=D0=B2=D0=BD=D1=8E=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8F=20=D0=BF=D0=BE=20=D0=BF=D1=96=D0=BA=D1=81?= =?UTF-8?q?=D0=B5=D0=BB=D1=8C=D0=BD=D1=96=D0=B9=20=D1=81=D1=96=D1=82=D1=86?= =?UTF-8?q?=D1=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Менше — на прохання. Чіткіше — виправленням того, чого бракувало з самого початку: полотно масштабоване на dpr, тож координата 9 при масштабі 1.25 дає 11.25 фізичного пікселя, і браузер розмазує літеру між двома. На дрібному шрифті це читається як «нечітко», хоча винен не розмір, а півпікселя зсуву. Тепер позиції округлюються до цілого пристроєвого пікселя. Розмиття зникає без жодної втрати, і саме тому шість пікселів тепер працюють там, де раніше не вистачало семи. --- web/src/components/Minimap.tsx | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/web/src/components/Minimap.tsx b/web/src/components/Minimap.tsx index 0dacc1b..24e5c5d 100644 --- a/web/src/components/Minimap.tsx +++ b/web/src/components/Minimap.tsx @@ -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.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 з'їхали б до лівого краю й структура зникла саме // там, де вона найпомітніша. 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) {