Найти тему
Игорь Назаров

Построение интерфейса. И зачем нужны шаблонизаторы?

Приложение для моделирования орбит постепенно насыщается новыми деталями.

В нем появляется пользовательский интерфейс, который позволяет перейти от жестко заданной в скрипте последовательности действий при старте программы на хотя бы ограниченный выбор того, что мы будем вычислять, анализировать и выводить на экран.

Рассмотрим на примере задачи отрисовки траекторий в относительном движении. Для этого сначала нужно выбрать объект, служащий опорной точкой, затем - выбрать любое количество объектов, траектории которых будут через вычитание векторов приведены к движению относительно опорного объекта.

Соответственно, нам нужен элемент управления, который позволял бы выбрать опорную точку из списка доступных , а также близкий по функционал элемент, для которых бы определялись параметры относительного движения. И было бы хорошо, чтобы в глазах не рябило от почти одинаковых списков на экране.

Конечно, мы могли бы внести сразу этот элемент в html-код, но мы до конца не знаем, сколько именно объектов будем моделировать, как эти объекты будут называть. А это значит, что рендерить элементы для выбора мы сможем только после чтения исходных данных. Скриптом.

Создание шаблонного раскрываемого списка
Создание шаблонного раскрываемого списка

Метод renderMultiselect создает нужную нам последовательность html-элементов, учит кнопку скрывать/показывать список, затем выдает нам ссылку на созданный элемент и на список находящихся внутри опций.

Можно ли сделать это каким-то другим способом?

Да, вполне. С подходящим набором инструментов. Например, с помощью Vue.js , React или Svelte. Эти библиотеки позволят явно задать в js-коде "шаблон" будущего html и отобразить зависимости между исходными данными и внешним видом компонента (Кстати, это - очень важное для нас слово).

Компонент - законченный и самодостаточный кусок html-разметки и связанные с ним скрипты js (которые наш компонент рендерят, навешивают обработчики, меняют состояние управляющих компонентом данных) и стилей css. В идеале компонент пишется один раз и потом используется в множестве не связанных друг с другом приложений

Создать компонент можно средствами чистого Js, но это громоздко и многословно.

React использует синтаксис JSX, с которым можно оперировать разметкой внутри скриптов так, словно это обычные переменные JS. Отпадают лишние операции с DOM-деревом. Из массива данных через оператор map можно вернуть массив однотипных компонентов - например, ячеек таблицы или элементов списка.

Пример синтаксиса JSX в приложении React. Старый проект по визуализации содержимого БД. Похоже на чистый html
Пример синтаксиса JSX в приложении React. Старый проект по визуализации содержимого БД. Похоже на чистый html

Vue.js более консервативен, в шаблонах содержится почти чистый html, а специальные v-директивы (v-if, v-else, v-for) позволяют подстроить процесс рендеринга под содержимое отображаемых данных. Если "Реакт" придется по душе тем, кто пишет скрипты, то Vue ближе верстальщикам и дизайнерам.

Но мы отвлеклись. Интерфейс - необходимый, но не первостепенный элемент приложения. Мы добавили в код методы по оценке вычислительных затрат и усовершенствовали вывод графики, отмечая рисками на графике точки, в которых все объекты модели были в заданный момент времени.

Кстати, по выводам программы можно определить, с какой скоростью течет время внутри модели.

Расчет для двух спутников, входящих в зону притяжения Луны. Движение - относительно Земли. Справа - лог программы.
Расчет для двух спутников, входящих в зону притяжения Луны. Движение - относительно Земли. Справа - лог программы.
Тот же расчет, но траектории перестроены относительно Луны.
Тот же расчет, но траектории перестроены относительно Луны.

За 6571 миллисекунду реального времени в модели прошло 3003000 секунд. 1 секунда - 5,28 дней модельного времени. Выбранный шаг интегрирования - 2.5 секунды. Чтобы собрать динамику за год, потребуется порядка 70 секунд машинного времени. Это - вполне терпимая величина. Для начала.

Одно из возможных направлений развития модели - создание гибкого интегратора, который мог бы подбирать шаг интегрирования под динамику процессов модели.

Пока взаимодействия между объектами слабые, а значения производных - маленькие, мы можем интегрировать с большим шагом по времени, возможно - что порядка минут или даже десятков минут. Но как только производные увеличиваются, шаг стоит уменьшить, чтобы просчитать близкие сближения с большей точностью.