Доступное управление и передача редактора
В предыдущих уроках мы построили модель, SVG, ввод, историю, сохранение и экспорт. Теперь рассмотрим редактор как цельный инструмент. Пользователь должен понимать, что выбрано, какое действие завершено и как продолжить после ошибки. Другой разработчик должен отличать подготовленные возможности от проверенных. К концу урока составим маршрут работы и передачу проекта без обещания ещё не подтверждённой готовности.
Полный проект «Схема» доступен в архиве исходников. Это законченный снимок учебного приложения, а не набор выполненных сборок каждого урока. Во время написания код не запускался и тесты не выполнялись. Ниже описаны сценарии для будущей технической проверки, а не отчёт об их прохождении.
Два пути к одному действию
Нажатие на рисунок и перетаскивание — только один способ работы. Список слоёв содержит настоящие HTML-кнопки. Панель свойств имеет подписанные поля и кнопку применения. Отдельные кнопки двигают выбранный объект на десять единиц. Благодаря этому основной набор изменений доступен без точного попадания указателем в небольшую фигуру.
Важна общая реализация команд. Клавиатурные кнопки используют moveShape(), форма и указатель заканчиваются принятием того же проверяемого документа. Если доступная панель начнёт жить по отдельным правилам геометрии, она быстро разойдётся с полотном. Доступность здесь возникает из архитектуры действий, а не только из добавленных атрибутов.
SVG имеет роль изображения и текстовое название. Само по себе это не превращает каждую фигуру в удобный объект для экранного диктора. В нашей версии семантический путь к объектам проходит через список. Для редактора сложных графов потребовались бы более подробные названия связей, структура групп и проверка реальными вспомогательными технологиями.
Названия и состояние элементов
Кнопки слоёв показывают подпись или тип и идентификатор. Выбранное состояние передаётся через aria-pressed. Поля размещены внутри подписанных элементов формы, а недоступная панель отключается через fieldset.disabled. Пользователь не должен отправить свойства, когда фигура не выбрана или выполняется перемещение.
Важно различать отсутствие возможности и ошибку. Если история пуста, «Отменить» отключено — это нормальное состояние. Если импорт повреждён, выводим сообщение и сохраняем рабочий документ. Если локальное хранилище недоступно, предлагаем скачать JSON. Один универсальный текст «Что-то пошло не так» не помогает решить эти разные задачи.
В CSS предусмотрен видимый фокус. Проверять его нужно при реальной работе клавиатурой: цветовая обводка, хорошо заметная на белом фоне, может быть слабой рядом с окрашенной кнопкой. Также нужно оценить порядок переходов после перестройки списка. Наш способ пересоздания элементов прост, но может потребовать улучшения сохранения фокуса при росте интерфейса.
Сообщения о результате
Область status сообщает о завершении перемещения, применении свойств, импорте и ошибках. Для неё используется ненавязчивое живое объявление. Мы не объявляем координаты на каждом pointermove: десятки сообщений подряд сделали бы редактор трудным для прослушивания. Во время движения меняется изображение, а сообщение появляется на границе операции.
Сообщение автосохранения может заменить текст предыдущего действия через 400 миллисекунд. Это допустимая простая версия, но при дальнейшем развитии полезно разделить подтверждение команды и состояние хранения. Иначе важное объяснение легко исчезнет из общей строки. Необходимо также решить, какие сообщения должны оставаться видимыми до исправления ошибки.
function commit(doc, message) {
history.commit(doc);
redraw();
saveLater();
if (message) announce(message);
}
Это общий путь завершённого изменения. Он показывает, где согласуются данные, интерфейс и запись. Внутри отдельных кнопок не приходится снова придумывать порядок действий. При расширении редактора полезно сохранять этот единый путь, а специализированные сообщения передавать аргументом.
Учебный маршрут пользователя
Начните с открытия примера. Выберите «Редактор» в списке, поменяйте подпись и примените форму. Сдвиньте объект кнопкой вправо, отмените и повторите. Затем выполните перетаскивание, прервите его Escape и убедитесь, что исходное положение восстановлено. После этого приблизьте сцену и верните весь лист.
Далее скачайте JSON, измените рисунок и импортируйте прежний файл. Ожидается замена модели с возможностью отмены. Выгрузите SVG и PNG: оба должны показывать полный лист без текущего выделения. Этот маршрут проходит через несколько подсистем, поэтому полезнее простого просмотра начальной сцены. Он остаётся планом проверки до фактического выполнения.
| Ситуация | Ожидаемое продолжение |
|---|---|
| Указатель отменён браузером | Возврат исходного положения и включение управления |
| Неверные свойства | Прежний документ и сообщение |
| Повреждённый JSON | Прежний документ и возможность выбрать другой файл |
| Ошибка localStorage | Работа в памяти и скачивание JSON |
| Не удалось получить PNG | Сообщение без фиктивного успеха |
Для проверки сенсорного ввода нужен реальный браузер и устройство либо обоснованная эмуляция. Наличие Pointer Events в коде не подтверждает, что все жесты удобны на телефоне. Аналогично наличие aria-live не доказывает качество озвучивания. Эти факты нельзя выводить только из чтения исходников.
Перед передачей полезно также описать данные, которые приложение не отправляет. В этой версии схема читается и сохраняется локально, серверной синхронизации нет. Но сам способ размещения редактора может добавить аналитику или сторонние ресурсы, поэтому вывод о приватности относится к конкретному набору файлов. Разработчик, который включит загрузку документов на сервер, должен заново объяснить пользователю этот переход и срок хранения.
Передача проекта
README перечисляет файлы, формат документа, пределы и способ локального открытия через HTTP-сервер. Модули разделены по смыслу: модель не зависит от DOM, рендерер создаёт изображение, файловый модуль отвечает за чтение и экспорт, main.mjs связывает интерфейс. Следующему разработчику проще найти место изменения, чем в одном длинном обработчике страницы.
Явно запишите ограничения: только прямоугольники и эллипсы, не более 200 фигур, история до сорока снимков, JSON до одного мебибайта. Нет соединительных линий, свободных путей, совместного редактирования, внешних картинок и автоматического переноса подписей. Эти функции можно добавить, но каждое расширение должно пройти через модель, ввод, историю и оба пути экспорта.
Например, добавление стрелки между объектами потребует устойчивых ссылок на идентификаторы и правила удаления связанной фигуры. Просто нарисовать линию в SVG недостаточно. Подобные изменения полезно начинать с договора данных, как мы сделали в первом уроке. Серия дала основу редактора, которую можно расширять последовательно, а техническую проверку, измерения и публикацию проводить отдельными осознанными этапами.