Месяц назад я вставила в свой симулятор девять чисел из научной статьи. Сегодня эти же девять чисел работают в четырёх местах, и последнее из них написала не я.
Что за матрица
В 2009 году Мачадо, Оливейра и Фернандес опубликовали физиологическую модель цветовосприятия — и посчитали для неё матрицы: как пересчитать обычный RGB-цвет в тот, который видит человек с дальтонизмом. Для полной дейтеранопии матрица выглядит так:
R’ = 0.367·R + 0.861·G − 0.228·B
G’ = 0.280·R + 0.673·G + 0.047·B
B’ = −0.012·R + 0.043·G + 0.969·B
Девять коэффициентов. Умножаете каждый пиксель — получаете картинку глазами дейтеранопа. Красный и зелёный сползаются в один горчичный, и статус «доставлен» перестаёт отличаться от «отменён».
У этой модели есть свойство, которое я ценю как бывший врач: она физиологическая, а не косметическая. Не «сделаем посерее», а модель отклика колбочек. Поэтому её используют и браузерные инструменты разработчика, и исследователи. И поэтому у неё есть шкала: матрицы посчитаны для разной тяжести, ведь у большинства людей потеря частичная. Аномальная трихромазия встречается заметно чаще полной дейтеранопии, а выглядит совсем иначе — интерфейс, который разваливается на 100%, на 40% может ещё держаться.

Дальше началось интересное: я стала переносить эти девять чисел из среды в среду. И каждая среда сопротивлялась по-своему.

Носитель первый: HTML-страница и SVG-фильтр
Первый симулятор — обычная страница на GitHub Pages. Готовые сценарии: статусы заказа, график, схема линий, фото. К каждому — исправленная версия, потому что показать поломку без рецепта — это половина работы.
Технически матрица здесь живёт в SVG-фильтре feColorMatrix: браузер сам умножает пиксели, мне остаётся подставить коэффициенты. Ползунок тяжести — линейная интерполяция между единичной матрицей и полной.
И здесь первая засада, о которой почти никто не пишет: feColorMatrix по умолчанию считает в linearRGB, а не в привычном sRGB. Это не баг, это спецификация. Результат на глаз близкий, но не побайтово идентичный тому, что даёт «лобовое» умножение пикселей. Для симулятора это допустимо — он показывает характер поломки, а не претендует на колориметрическую точность. Но знать об этом надо, если вы вдруг решите сверять свой фильтр с чужим скриншотом.
Носитель второй: canvas и пиксельный цикл
Потом я добавила загрузку своего макета — и SVG-фильтр перестал подходить: мне нужен был результат, который можно рассматривать и сохранять, с предсказуемым цветовым путём. Здесь матрица работает в лоб: canvas, getImageData, цикл по пикселям, умножение, putImageData.
for (var i = 0; i < px.length; i += 4) { var r = px[i], g = px[i+1], b = px[i+2]; px[i] = clamp(m[0]*r + m[1]*g + m[2]*b); px[i+1] = clamp(m[3]*r + m[4]*g + m[5]*b); px[i+2] = clamp(m[6]*r + m[7]*g + m[8]*b);}
Скучно? Да. И в этом достоинство: путь sRGB, никакой магии между мной и пикселем. Скриншот 4К — восемь миллионов пикселей — обрабатывается за десятки миллисекунд, для интерактива хватает.
Так в одном инструменте оказалось два пути одной матрицы: фильтр для живых сценариев, цикл для загруженных картинок. Результаты чуть различаются — и я оставила это как есть, потому что честнее иметь два предсказуемых пути, чем один «усреднённый».
Носитель третий: Figma, где холст трогать нельзя
Дальше логичный шаг: дизайнеры живут не на моей странице, а в Figma. Значит, матрица должна прийти к ним.
И тут среда сопротивляется сильнее всего. Первое, что нужно принять: плагин не может перекрасить холст Figma живьём. API такого не даёт — и, подозреваю, правильно делает. Пришлось строить обходной маршрут: выделяете фрейм → плагин экспортирует его в PNG → в панели тот самый пиксельный цикл → по кнопке симуляция кладётся на холст рядом с оригиналом, с подписью «Дейтеранопия 100%». Из ограничения вырос жанр: подписанный артефакт для хендофа — симуляцию можно оставить в макете для команды.
Второе сопротивление интереснее. В веб-версии «Посмотри моими глазами» у меня был тремор: кнопка убегает от курсора, и ты телом чувствуешь, каково это. В Figma эта механика невозможна — кнопка на экспортированной картинке уже растр, убегать ей нечем. Честный перенос «в лоб» здесь был бы враньём: у человека с тремором дрожит рука, а не мир.
Пришлось переизобретать: в панели плагина курсор дрожит (сумма синусоид 4–7 Гц плюс шум — похоже на паркинсонический тремор), а клик по кнопке макета высыпает облако из 24 симулированных попыток нажать. Сколько точек легло мимо кнопки — столько промахов у реального человека. Неожиданно это оказалось нагляднее убегающей кнопки: разброс видно, его можно положить на холст и показать команде как аргумент за крупные цели.

С дислексией — обратная история: Figma дала то, чего у веба не было. Плагин имеет доступ к живому тексту макета, поэтому режим дислексии не рисует поверх растра, а создаёт рядом копию фрейма, где внутренние буквы слов перепутаны — первая и последняя на месте, длина строки не меняется, вёрстка не едет, оригинал не тронут. «Добавить в корзину» → «Дбватоиь в кзоирну».

Из этого опыта я вынесла правило, которое теперь применяю ко всем переносам: не тащи механику — тащи смысл. Механика принадлежит среде. Смысл переносится.
Так появились два плагина: «Посмотри моими глазами» — восемь линз от катаракты до дислексии, и «Цвет, который ты не видишь» — прицельно про цветовосприятие, с полной шкалой типов и тяжести. Оба работают офлайн и ничего никуда не отправляют — для инструмента про доступность это не техническая деталь, а обещание.
Носитель четвёртый: Chrome, который сделала не я
А потом матрица ушла из моих рук — и это лучшая часть истории.
Разработчик Сергей Бухарев увидел мой симулятор и собрал на его основе расширение для Chrome: те же состояния восприятия, но на любом живом сайте, прямо во вкладке. И пошёл дальше — добавил регулируемую катаракту, два варианта тремора, режимы, до которых я не додумалась. Сохранил принцип: всё локально, ничего не собирается.
В медицине знание по умолчанию работает так: публикуешь протокол — по нему лечат люди, которых ты никогда не увидишь. Я восемь лет работала в этой логике и не ожидала встретить её в дизайне. Оказалось, инструменты умеют то же самое, если их отпустить.
Про честность, без которой всё это не имеет смысла
Каждый из четырёх носителей — приближение. Матрица Machado моделирует физиологию, но не зрение конкретного человека: дальтонизм у каждого свой. Симулятор показывает характер поломки — где интерфейс перестаёт различаться, — и этого достаточно, чтобы поймать красно-зелёную пару статусов до релиза. Но единственный надёжный тест был и остаётся прежним: показать макет человеку, который так видит.
И правило, ради которого затевались все четыре носителя, умещается в одну строку: цвет не должен быть единственным носителем смысла. Иконка, подпись, паттерн — второй признак спасает каждого двенадцатого мужчину среди ваших пользователей.
Всё в одном месте
-
Симулятор дальтонизма (4 типа × тяжесть, свой макет)
-
Симулятор восприятия (одна карточка — шесть режимов восприятия)
-
Плагин Figma «Посмотри моими глазами»
-
Плагин Figma «Цвет, который ты не видишь»
-
Расширение Chrome «Симулятор восприятия» (автор — Сергей Бухарев)
Всё бесплатное, всё работает локально. Если соберёте пятый носитель — напишите, мне правда интересно, как матрица поведёт себя там.
Про доступность без сложных слов пишу в телеграм-канале
ссылка на оригинал статьи https://habr.com/ru/articles/1062846/