При проектировании системы видеонаблюдения большого объекта потребовалось разместить камеры на плане, учитывая их углы обзора/наклона и получаемую плотность пикселей (необходима для определения зон задач идентификации, распознавания и т. п.). Вcпомнил математику 8 класса и сделал параметрический блок для AutoCAD, потом захотелось большего — чтобы прикинуть расстановку камер мог каждый желающий. Только была небольшая проблема — я не программист...

БОЛЬШОЕ СПАСИБО всем тем, кто делится различными обучающими материалами — именно благодаря вам можно попробовать сделать что‑то новое.
Статья можно сказать уровня «джунам от джуна» или немного о том, как можно написать свое приложение отличное от калькулятора и to‑do листа. Сейчас, когда смотрю на итоговый результат, иногда думаю: «Это точно я сделал?»:)
Небольшое замечание
На Хабре мы с братом «сидим» под одним ником, поэтому пусть вас не смущает, что часть статей в профиле написана программистом:) Он же мне и помогал в освоении JS и всячески поддерживал, хотя кажется не верил, что я доделаю проект до уровня, чтобы можно было показать не сильно краснея.
Предисловие
Листая Хабр, наткнулся на любопытный пост Эффективный расчёт области видимости и линии взгляда в играх — как раз то что нужно, чтобы начать осуществлять задуманное.
Решено — это будет SPA‑приложение, а для его создания нужно подучить JavaScript. Не так страшно, когда есть Замечательный учебник, статьи на Хабре и Stackoverflow — место, где можно найти ответы на свои вопросы (не всегда верные или идеальные, но лучше, чем ничего). СSS и HTML на простейшем уровне я уже немного знал.
Как оказалось, встроенный в JS канвас весьма примитивен, и тут встретился цикл статей «Знакомимся с Fabric.js» 1, 2, 3, 4 (это «перевод» части справки фреймворка, но я тогда об этом не знал). Fabric.js создает весьма удобный дополнительный слой абстракции, с помощью которого объекты канваса становятся JS‑объектами и манипуляции идут уже с ними.
Можно было попробовать реализовывать на Pixijs (статья), но я счел избыточным такой фреймворк для моей задачи.
Так потихоньку ковыряя JS и решая простейшие математические задачи с помощью статей (1, 2, 3), я «выпустил» первую версию программы (видео). Ее пришлось «забросить», так как на работ�� засел за изучение новых для меня тем.
Спустя год
Вернувшись к проекту, я его критически осмотрел и понял: нужно сделать рефакторинг кода, устранить ошибки, немного улучшить внешний вид и расширить функционал. Серверную часть мне согласился написать брат (Node.js, express, SQLite).

Выбор инструментария
Ранее при создании менюшек и диалогов очень раздражали постоянные querySelector и обработка eventListner, поэтому решил, что нужно подучить что‑то модное, чтобы жизнь была веселее. Выбор пал на Vue 2 (Vue.js), так как обещался низкий порог входа и развитое сообщество (Vue 3 не рискнул именно из‑за «новизны»).
Для «вкатывания» во Vue очень помог цикл статей Vue.js для начинающих (ссылка на 11 урок, так как в нем есть ссылки на все остальные уроки), хотя в комментариях писали «Для кого это? Кто не умеет читать документацию?!». Ну хотя для тех у кого нет опыта работы с другими фреймворками и еще не умеют читать код «фрагментами без обвязки».
Если раньше я писал код JS в Atom, то с изучением Vue открыл для себя VS Code (с плагином Vetur), а также встроенных помощников в vue‑cli — контроля внешнего вида кода ESLint и систему сборки проекта на базе webpack. Для ведения версий файлов начал использовать GitHub Desktop. Жить стало веселее.
В первой версии программы хранен��е данных у меня было в глобальных переменных, в экосистеме Vue для этого есть Хранилище (Store) Vuex с немного загадочной для начинающего логикой. Помогли разобраться полезные статьи и ценные комментария в них — 1, 2, 3. Хотя сейчас топят за pinia, переписывать уже не стал.
Очень сильно при отладке помогает расширение для браузера — Vue Devtools, которое добавляется в «Панель для разработчика».
Для получения данных с API остановился на Axios: Axios или Fetch: чем пользоваться в 2019 году?
Для канваса так и ост��лся Fabric.js.
Архитектура проекта
Ранее я не сильно заморачивался архитектурой (с JS бы совладать), но при рефакторинге стало понятно, что при создании редактора канваса нужно отделять сущности:

Объекты — линии, прямоугольники, камеры и т. п., которые состоят из нескольких объектов fabric.js и вспомогательных данных (типа id, type и т. п.).
Layout Manager — ничего не знает о fabric.js и о внутреннем устройстве объектов, а только манипулирует ими на основании id/type и публичных методов. Хранит в себе перечень объектов для канваса.
Canvas Editor — почти ничего не знает об объектах (совсем оторвать не получилось и пришлось сделать пару костылей). Выкладывает на канвас то, что ему передает Layout Manager, а также обновляет данные в Хранилище. Отвечает за канвас и манипуляции с ним.
Хранилище — хранит в себе информацию обо всех объектах проекта в минимальном виде, но только в глобальных координатах (а не координатах канваса). Так например, зоны обзора строятся каждый раз заново. Используется как источник данных для сохранения и загрузки данных проекта. Является более общим хранилищем данных, чем хранилище объектов в Layout Manager, так как содержит данные нескольких площадок (канвасов).
Получилось «не очень», но все равно стало удобнее работать. Эх вышла бы немного пораньше статья Frontend архит��ктура MVP (Model‑View‑Presenter).
Vuex разбил на модули по функционалу (а не как чаще делают по Actions, Mutations и т. п.):
авторизация,
перечень проектов,
данные графического редактора (инициализируются при выборе проекта):
перечень площадок,
перечень объектов,
данные для расчета системы хранения видеонаблюдения,
настройки.
Авторизация сделана на базе токена (строки), получаемой от бекенда и хранимой в HttpOnly coockie. Просто и незамысловато:)
Немного о Fabric.js
К сожалению, он хоть и дает возможность оторваться от манипулирования канвасом, но остается весьма своеобразным. Так линия — это нарисованная диагональ в BBox (boundary box). Все хорошо, пока не захочется ее отредактировать с помощью ручек BBox — толщина линии становится слабо управляемой. В итоге от предоставляемых ручек решено было отказаться и сделать свои, например, у меня линия — это 4 объекта fabric.js (без отображения BBox): сама линия (перерисовывается при таскании ручек), 2 ручки‑кружочка и вспомогательная скрытая линия для более «цепкого» выделения.
Аналогично, решение для зумирования, предлагаемое авторами фреймворка меня не устроило из‑за «расплывающихся» объектов и ограниченности рабочей области. В итоге зумирование и панирование сделал без встроенных в фреймворк методов (путем перерасчета объектов).
Графический интерфейс
Придумать графический интерфейс с нуля не так‑то прос��о, как может показаться на первый взгляд.
В первой версии я «вдохновлялся» ленточным интерфейсом от Microsoft — получилось что‑то «так себе». Поговорил со знакомым маркетологом, тот сказал — смотри веб‑интерфейсы программ для дизайнеров (figma, supa и т. п.). Посмотрел, переработал, добавил пару подсмотренных идей у Яндекс‑карт и конфигуратора серверов Dell:0.
Конечно, можно попробовать самому сделать более‑менее симпатичные элементы интерфейса, но для pet‑проекта imho использование UI‑фреймворка более чем достаточно и был взят Vuetify (хотя также есть альтернативный Quasar, который выглядит «корпоративненько»:) ). Благодаря Vuetify не пришлось хотя бы с отступами сильно возиться и адаптивностью (хотя благодаря flexbox сейчас не нужны всякие грязные трюки с CSS). Также Vuetify предоставляет элементы с широким функционалом настройки — например, data‑tables: ничего самому писать не надо, остается только сконфигурировать. Говорят, что Vuetify потихоньку помирает, но это не точно.
Что еще?
Так как системы видеонаблюдения делаются не только у нас в стране, решил добавить мультиязычность (i18n) — оказалось не так сложно (к сожалению доступ к статье на Хабре закрыт, поэтому ссылка на сторонней ресурс «зеркало»). Программы для создания JSON‑файлов перевода не нашел, поэтому их веду в Excel, который мне через формулу собирает JSON‑строку, которую я уже копир��ю в файлы локализации. Так себе решение и что‑то нужно с эти делать, хотя бы кнопку в файле xls‑прилепить, при нажатии на которую файлики локализации будут перезаписываться:)
Чтобы все было как у «взрослых» конечно же потребовался роутинг (работа со строкой ввода) — тут все стандартно Vue Router. Не стоит забывать, что пользователь может и страницу перезагрузить и кнопками браузера «вперед/назад» попользоваться.
Программа предназначена больше для наружного видеонаблюдения (в помещениях и так примерно ясно, как будет показывать), поэтому добавил вставку плана из OpenStreetMap (OSM c OpenLayers). Если внезапно:) будет большой спрос на вставку карт, то можно развернуть карты на сервере (а не использовать внешний API), а вот за Google‑карты и Яндекс‑карты при превышениях лимитов уже нужно будет платить.
Данные о камерах у меня есть — так почему же не прикрутить расчет системы хранения? Ничего сложного, только основная характеристика — битрейт от камер сильно зависит от снимаемой сцены. Но все‑таки как‑то емкость архива нужно прикидывать — в итоге нашел рекомендации Hikvision, которые и легли в основу расчетов.
Казалось бы вот и все — приложение готово, можно и выпускаться. Какая же программа без справки? Разработка документации на VuePress. Все хорошо, но есть нюанс — подготавливать графические материалы (например, картинки с выносками над элементами управления) нужно в какой‑нибудь другой программе. К тому же теряется интерактивность. Попробовал Dr.Explain — не впечатлило, хотя что‑то в нем есть: для создания толмутов документации для госструктур наверное годный продукт. Опять же наличие упоминаний «Сделано в Dr.Explain» в бесплатной версии ПО как‑то не очень. Поиски бесплатных аналогичных программ для документирования ничего не дали. В итоге остановился на VuePress.
И последний штрих — создание небольшого видеоролика про кролика Как снять обучающий видеоролик: 10 секретов технического писателя. Захват экрана делаю в CamStudio, а для аудио использую Audacity.
Тестирование, автотесты, QA — наверное что‑то хорошее, раз так много на Хабре о них часто пишут. Не знаю:)
Разве��тывание приложения
Приложение написано, остается поработать немного DevOps:
Собрать проект: в моем случае vue‑cli все делает за меня — минифицирует и склеивает всю кучу моих мелких файлов в несколько больших JS‑ и CSS‑ файлов.
Зарегистрировать веб‑домен: при выборе регистратора заметил, что нужно смотреть, сколько будет стоить продление на следующий год, а не первоначальный платеж‑замануха.
Оформить SSL‑сертификат: сайты с доступом по http сейчас «не котируются». SSL‑сертификат можно получить у регистратора/хостера (как правило за денежку на год) или, как вариант, раз в 90 дней получать его в Let's Encrypt.
Завести сервер: реальную железку или арендовать виртуальный (виртуальную машину). Мне было проще поднять дома, так как имеется «белый» ip‑адрес, используя небольшой безвентиляторный ПК на базе Celeron J1900 / 4Gb. На него накатил Linux Mint 21, удаленный доступ (tigervnc), node.js и прочие мелочи. Отказоустойчивость данного решения — ну совсем «так‑себе», потом как‑нибудь переделаю.
Настроить веб‑сервер, который будет отдавать JS‑файлы: в моем случае — nginx. В случае размещения сервера дома нужно еще пробросить порты на маршрутизаторе.
Поднять почтовый сервис для регистрации пользователей и поддержки или воспользоваться готовым (например, я использовал VK WorkSpace с бесплатным базовым тарифом — не знаю, доступен ли тариф сейчас).
Почесать репу дня три и получить итоговый результат.
Для тех, кто не хочет регистрироваться, но желает пощупать — есть тестовая учетная запись: test@survy.ru / 123 (просьба не «шалить»).
Что впереди?
Проект все равно еще на стадии MVP: нужно делать учет дисторсии объективов (тут уже математикой 11 класса пахнет), hotkeys, отмену последних действий и т. п. — что уже есть «у всех». Исправление багов также никто не отменял.
P. S. Для тех кто дочитал: вам фронтендер не нужен?:)
