На кухонной панели с семидюймовым экраном открывается сайт доставки продуктов, и половина кнопок не помещается в видимую область. Пользователь тычет пальцем в элемент размером с горошину, промахивается и уходит к холодильнику за телефоном. Знакомая ситуация для тех, кто пробовал переносить обычный сайт на устройство с необычным экраном. Разбираемся, чем такие экраны отличаются и как строить интерфейс, который на них работает.
Устройства интернета вещей отличаются от телефонов по четырём параметрам
Первое отличие это физический размер экрана. Панели бывают от двух до пятнадцати дюймов, и это не тот диапазон, к которому привыкли мобильные разработчики. Малый размер означает, что места для второстепенных элементов нет.
Второе отличие это расстояние до пользователя. Телефон держат в руках, а панель висит на стене или стоит на столе. На расстоянии вытянутой руки мелкий шрифт неразличим, поэтому базовый размер текста приходится увеличивать. Практическое правило: минимальный кегль на таком экране заметно выше, чем на телефоне.
Третье отличие это способ ввода. Часть устройств управляется касанием, часть физическими кнопками, часть голосом. Бывают панели вовсе без экрана, где интерфейс сводится к паре индикаторов и одной кнопке.
Четвёртое отличие касается вычислительных ресурсов. Устройство может иметь слабый процессор, мало памяти и медленное соединение. Тяжёлый сценарий с десятком библиотек превратит загрузку в пытку, а анимации будут дёргаться.
Из этих четырёх пунктов вытекает пятый, неочевидный. Такой интерфейс редко бывает основным местом работы. К нему подходят на минуту, чтобы выполнить одно действие. Значит, глубина навигации должна быть минимальной.
Основой служит адаптивная верстка с точками перехода по возможностям
Адаптивность начинается с метатега в заголовке документа, который сообщает браузеру, что страница умеет подстраиваться под ширину:
<meta name="viewport" content="width=device-width, initial-scale=1" />
Дальше применяются точки перехода. Но в отличие от привычной верстки, ориентированной на телефоны и ноутбуки, здесь стоит опираться на возможности устройства, а не только на ширину.
Медиазапросы проверяют характеристики среды. Можно учесть ориентацию, разрешение, схему ввода. Схема ввода особенно полезна: она позволяет отличить палец от мыши и от клавиатуры.
/* базовые стили для панели */
:root {
font-size: 20px;
--touch-target: 64px;
}
/* вертикальная панель */
@media (orientation: portrait) and (max-width: 800px) {
.layout {
grid-template-columns: 1fr;
}
}
/* горизонтальная панель */
@media (orientation: landscape) and (min-width: 801px) {
.layout {
grid-template-columns: 320px 1fr;
}
}
/* управление пальцем */
@media (pointer: coarse) {
.control {
min-height: var(--touch-target);
min-width: var(--touch-target);
}
}
Размер базового шрифта в двадцать пикселей выглядит вызывающе для веб-разработчика, привыкшего к шестнадцати. Но для панели на стене это норма: текст должен читаться с полутора метров.
Второй приём касается единиц измерения. Абсолютные пиксели в макете привязывают интерфейс к конкретному устройству. Относительные единицы и множители позволяют менять масштаб целиком, не переписывая верстку. Это удобно ещё и потому, что панели с одинаковым разрешением встречаются с разной плотностью пикселей.
Третий приём связан с контейнерными запросами. Они позволяют компоненту подстраиваться под ширину родительского блока, а не всего окна. Для панелей с блочной раскладкой это точнее, поскольку один и тот же виджет может занимать разные части экрана.
Сенсорное управление требует крупных целей и щедрых отступов
Пальцем в мелкую кнопку попасть трудно, а на вертикальной панели еще и неудобно. Минимальный размер цели для касания давно определён: около сорока четырёх пикселей по меньшей стороне. Для панели это значение стоит увеличить до шестидесяти четырёх.
Второе требование это расстояние между целями. Соседние кнопки, стоящие вплотную, приводят к случайным нажатиям. Отступ в восемь пикселей это нижняя граница, комфортная начинается с двенадцати.
Третье требование касается визуальной обратной связи. На телефоне палец закрывает место нажатия, и пользователь ориентируется на изменение цвета. На панели экран виден целиком, поэтому отклик должен быть заметным: изменение фона, лёгкое увеличение, появление рамки.
Четвёртое требование связано с жестами. Прокрутка, масштабирование двумя пальцами и перетаскивание на панели часто неудобны или невозможны. Лучше строить интерфейс так, чтобы все действия выполнялись одиночными нажатиями.
.button {
min-height: 64px;
min-width: 64px;
padding: 12px 20px;
font-size: 1.1rem;
border-radius: 12px;
border: 2px solid transparent;
transition: background-color 120ms ease, transform 80ms ease;
}
.button:active {
transform: scale(0.97);
background-color: #dbeafe;
}
.button:focus-visible {
border-color: #1f6feb;
outline: none;
}
Обратите внимание на последнее правило. Фокус по клавиатуре на панелях тоже нужен: часть устройств управляется пультом с кнопками, а часть имеет подключённую клавиатуру. Игнорирование фокуса делает такие устройства бесполезными.
Ограниченные ресурсы диктуют строгую экономию
Слабое устройство не прощает расточительности. Разберём, где именно теряется производительность.
Первое место это загрузка. Большая библиотека ради одной кнопки не оправдана. Для панели разумно писать на стандартных средствах браузера и подключать только то, что действительно нужно.
Второе место это анимации. Плавность обеспечивается аппаратным ускорением, но не все эффекты его получают. Свойства, вызывающие пересчёт разметки, обходятся дорого. Анимировать стоит преобразования и прозрачность, а не размеры и отступы.
/* хорошо: только преобразование */
.panel-enter {
transform: translateY(8px);
opacity: 0;
}
.panel-enter-active {
transition: transform 160ms ease, opacity 160ms ease;
}
.panel-enter-to {
transform: translateY(0);
opacity: 1;
}
Третье место это постоянные обновления. Живые часы, счётчики, таймеры перерисовываются каждую секунду. На слабом процессоре это заметно. Обновлять стоит только видимые элементы, а при уходе со страницы останавливать обновление вовсе.
Четвёртое место это изображения. Панель не нуждается в фотографиях высокого разрешения. Правильно подобранный формат и точные размеры экономят и трафик, и память.
Пятое место это шрифты. Подключение нескольких начертаний с полным набором символов утяжеляет загрузку. Для панели достаточно одного начертания и подмножества символов.
Офлайновая работа важна там, где связь нестабильна
Устройства интернета вещей часто стоят в местах с плохим сигналом: подвал, производственный цех, склад. Интерфейс обязан переживать пропадание связи.
Сервис-воркер кэширует оболочку приложения и отдаёт её даже без сети. Этого достаточно, чтобы интерфейс открывался и показывал последние известные данные.
const CACHE = "panel-v3";
const SHELL = ["/", "/styles.css", "/app.js", "/offline.html"];
self.addEventListener("install", (event) => {
event.waitUntil(
caches.open(CACHE).then((cache) => cache.addAll(SHELL)),
);
});
self.addEventListener("fetch", (event) => {
if (event.request.method !== "GET") {
return;
}
event.respondWith(
caches.match(event.request).then((cached) => {
const network = fetch(event.request)
.then((response) => {
const copy = response.clone();
caches.open(CACHE).then((cache) => cache.put(event.request, copy));
return response;
})
.catch(() => cached || caches.match("/offline.html"));
return cached || network;
}),
);
});
Такая стратегия отдаёт сохранённое сразу и обновляет кэш в фоне. Пользователь видит мгновенный отклик, а данные незаметно освежаются.
Второй элемент это локальное хранилище. Изменения, сделанные без сети, складываются в очередь и отправляются при восстановлении соединения. Важно обеспечить устойчивость: если устройство выключится посреди работы, данные не должны потеряться.
Третий элемент это индикация состояния. Пользователь обязан видеть, что связи нет и данные могут быть устаревшими. Молчаливое поведение хуже явного предупреждения.
Идентификация устройства и удалённое управление требуют осторожности
Панели часто именуются по месту установки: склад, цех, переговорная. Приложение подстраивается под роль устройства, показывая нужный набор функций.
Первый способ идентификации это адрес страницы с параметром. Просто, но параметр легко подделать и неудобно менять.
Второй способ это сохранённая настройка в локальном хранилище. Устройство запоминает роль при первом запуске, и дальше подстраивается само.
Третий способ это учётная запись с привязкой устройства. Самый надёжный вариант: сервер знает, какая панель где стоит и что ей разрешено показывать.
async function resolveRole() {
const saved = localStorage.getItem("panel-role");
if (saved) {
return saved;
}
const response = await fetch("/api/panels/me");
if (!response.ok) {
return "guest";
}
const { role } = await response.json();
localStorage.setItem("panel-role", role);
return role;
}
Отдельная тема это удалённое обновление. Панель, висящая на стене в другом городе, не обновишь вручную. Хорошая практика состоит в том, чтобы приложение само проверяло наличие новой версии и перезагружалось в удобный момент, например ночью, когда рядом никого нет.
Здесь важно не переусердствовать. Принудительная перезагрузка во время работы оператора раздражает. Плавный вариант: показать уведомление и позволить отложить обновление до завершения смены.
Тестирование проводится на реальных устройствах и в реальных условиях
Эмуляция в браузере даёт лишь приблизительное представление. Настоящие проблемы обнаруживаются только на железе.
Первое, что стоит проверить, это читаемость на расстоянии. Нужно отойти на полтора метра и попробовать прочитать подписи. То, что кажется крупным на мониторе разработчика, на панели окажется мелким.
Второе это точность попадания. Тест с настоящим пальцем показывает, где расположены неудобные цели. Особенно страдают элементы у краёв экрана и в углах.
Третье это поведение при плохой сети. Ограничение скорости и периодическое отключение показывают, как приложение переживает пропадание связи. Ошибки обнаруживаются именно здесь.
Четвёртое это длительная работа. Панель может не выключаться неделями, и утечка памяти проявится именно на длинном интервале. Полезно оставить устройство включённым на несколько суток и проследить за потреблением.
Пятое это разные ориентации. Панель могут повернуть при монтаже, и верстка должна переживать поворот без потери функций.
Разбор требований начинается с ответа на пять вопросов о рабочем месте
Прежде чем рисовать макет, полезно ответить на несколько вопросов. Ответы чаще всего меняют планировку сильнее, чем любые технические приёмы.
Первый вопрос: на каком расстоянии находится человек. Если панель висит на стене в цеху, читаемость важнее плотности информации. Если устройство лежит на столе под рукой, можно позволить более мелкий текст и больше элементов.
Второй вопрос: сколько времени занимает типичное взаимодействие. Для панели, к которой подходят на десять секунд, весь сценарий должен укладываться в одно-два нажатия. Если человек работает за устройством смену, навигация может быть глубже.
Третий вопрос: какими руками пользуются. Работник в перчатках не попадёт в мелкую цель, а сварочные перчатки исключают работу с сенсором вовсе. В таких условиях физические кнопки оказываются надёжнее экрана.
Четвёртый вопрос: что происходит при ошибке. Если неверное нажатие запускает оборудование, нужны подтверждения и блокировки. Если оно просто открывает лишний экран, достаточно лёгкой отмены.
Пятый вопрос: кто обслуживает устройство. Если обновлять приложение придётся местному сотруднику, процедура обязана укладываться в одну инструкцию. Сложный регламент на объекте не выполняется никогда.
Ответы на эти вопросы стоит записать и вернуться к ним при приёмке. Часто выясняется, что половина запланированных функций не нужна, а нужная не помещается в текущую верстку.
Ошибки проектирования обходятся дороже, чем в веб-приложении
У панелей есть неприятная особенность: их трудно исправить после установки. Устройство висит на стене в другом городе, и обновление требует поездки или удалённого доступа, которого может не быть.
Первая ошибка это перенос обычного сайта без переделки. Получается интерфейс с мелким текстом и глубокой навигацией, которым невозможно пользоваться.
Вторая ошибка это экономия на индикации состояния. Пользователь не понимает, идёт ли загрузка, отправлен ли запрос, есть ли связь. На панели это выглядит как зависание.
Третья ошибка это использование всплывающих подсказок, появляющихся при наведении. На сенсорном экране наведения не существует, и подсказка никогда не покажется.
Четвёртая ошибка это длинные формы. Ввод текста пальцем на вертикальной панели мучителен. Формы стоит сокращать до выбора из готовых вариантов, а ввод оставлять для редких случаев.
Пятая ошибка это игнорирование выгорания экрана. Статичная картинка на жидкокристаллической панели, работающей круглосуточно, оставляет след. Полезно предусмотреть лёгкое смещение элементов и режим гашения после простоя.
Шестая ошибка это отсутствие перезапуска. Любое устройство иногда зависает. Кнопка перезапуска в интерфейсе или аппаратная кнопка на корпусе избавляет от необходимости объяснять по телефону, как выдернуть питание.
Все эти пункты объединяет одно свойство: их дешевле учесть на этапе макета, чем исправлять на установленном устройстве. Именно поэтому проектирование интерфейса для панели начинается не с кода, а с наблюдения за тем, как люди работают рядом с ней.
Заключительная проверка перед сдачей экономит нервы заказчику и разработчику
Перед выпуском полезно пройтись по короткому списку.
Убедиться, что базовый размер текста читается с рабочего расстояния. Проверить, что каждая цель касания не меньше шестидесяти четырёх пикселей по меньшей стороне. Отключить сеть и посмотреть, что покажет интерфейс. Оставить устройство на сутки и проверить потребление памяти. Повернуть панель и убедиться, что верстка перестроилась. Открыть приложение с клавиатуры и пройти основной сценарий без мыши.
Шесть проверок занимают час, а предотвращают поток жалоб. В мире панелей час наблюдения стоит дороже дня программирования, потому что исправление на объекте стоит на порядок больше, чем за тем же столом.
Интерфейс для умных устройств получился упражнением в ограничениях. Здесь нет места украшениям, зато каждое решение проверяется реальностью: видно ли с расстояния, попадает ли палец, открывается ли при плохой связи. Тот, кто проектирует с оглядкой на эти вопросы, получает панель, к которой подходят без раздражения. А это и есть единственный измеримый признак хорошего интерфейса.