Location 26.400.0: MapLibre GL для карты отметок в мобильном Битрикс24
Почти весь дифф location 26.400.0 — JavaScript карты отметок (check-in), которую показывает мобильный Битрикс24. У карты появился второй движок, MapLibre GL, он включается фича-флагом, а по умолчанию работает прежний Leaflet. PHP-API с 26.300.0 не менялся, схема БД тоже, серверный код интеграций обновление не задевает. Модуля stafftrackmobile, который выводит эту карту, в нашем эталоне БУС нет, поэтому поведение разобрано по коду.
Новое
Переключите карту отметок на MapLibre
Движок выбирает config.php расширения location.check-in:
- Параметр запроса
mapEngine, если в нёмmaplibreилиleaflet. Другие значения игнорируются. - Иначе опция
check_in_map_engineмодуляstafftrackmobile. Всё, кромеmaplibre, означает Leaflet. - Без опции остаётся Leaflet.
Выбор попадает в JS через сообщение LOCATION_MOBILE_MAP_ENGINE. Движок location.osm.check-in-maplibre вместе с библиотекой (её min-версия весит около мегабайта) подключается через post_rel и только при выбранном maplibre, так что с Leaflet страница его не грузит.
Посмотреть новый движок один раз можно, дописав ?mapEngine=maplibre к адресу страницы с картой. На тестовом портале флаг включается для всех так:
<?php declare(strict_types=1);
use Bitrix\Main\Config\Option;
// флаг читает location, а хранится он в опциях stafftrackmobile
Option::set('stafftrackmobile', 'check_in_map_engine', 'maplibre');
// вернуть Leaflet:
// Option::delete('stafftrackmobile', ['name' => 'check_in_map_engine']);
Только MapLibre-движок умеет дорисовывать маршрут анимацией, рисовать стрелки направления с зума 15 и красить линию градиентом «свежести». Включается это, если хост передал animated, слой типа arrows или gradientStops. Кода хоста (stafftrackmobile) в эталоне нет, но, судя по комментариям в location, он этим пользуется. Ещё MapLibre ловит тап по линии маршрута с допуском 10 px. На дальнем зуме у стопки отметок прячется счётчик «×N». Его скрывает класс ci-zoom-far, а вешает этот класс колбэк onZoomChanged, который вызывает только MapLibre-движок.
Ловите новые события карты
В CheckInMapEventType из location.core три новых типа: LAYER_CLICKED, ZOOM_CHANGED и ENGINE_FALLBACK. Первые два шлёт только MapLibre-движок. ENGINE_FALLBACK с полями requestedEngine и actualEngine приходит, когда запрошенного движка на странице нет и карту поднял Leaflet. По нему хост понимает, что стрелок и кликов по линии не будет. Событие отправляется только при наличии BXNativeBridge, то есть в приложении. В браузере остаётся console.error со строкой Check-in map engine "maplibre" is not loaded, по ней и ищите причину, если флаг включён, а карта не изменилась.
Движки живут в реестре BX.Location.OSM.CheckInEngineRegistry с методами register(code, class) и get(code). MapLibre-движок регистрирует себя сам при загрузке, поэтому location.osm от него не зависит. Класс движка должен наследовать CheckInMapServiceBase. Раньше OSM требовал экземпляр Leaflet-сервиса CheckInMapService, теперь instanceof проверяется по базовому классу. Зарегистрировать свой движок технически можно, но штатно его не выбрать, потому что config.php пропускает только maplibre и leaflet.
Возьмите MapLibre для своей карты
Расширение location.osm.maplibre — это MapLibre GL JS 5.24.0 под лицензией BSD-3 вместе с CSS, без обёрток. В сборке его импортируют как import { maplibregl } from 'location.osm.maplibre', без сборки берут BX.Location.OSM.maplibregl. Расширение служебное и без документации, так что версия библиотеки может смениться с любым обновлением модуля.
Тайлы понадобятся свои. Авторизация к тайл-серверу Битрикса (класс OsmAuthProtocol, схема osmauth://) спрятана внутри движка отметок и не экспортируется. Своё расширение в /local/js/vendor/route-map/ подключает библиотеку обычной зависимостью:
<?php declare(strict_types=1);
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true)
{
die();
}
return [
'js' => 'dist/route-map.bundle.js',
'rel' => ['location.osm.maplibre'],
'skip_core' => true,
];
import { maplibregl } from 'location.osm.maplibre';
export function createRouteMap(container)
{
return new maplibregl.Map({
container,
style: {
version: 8,
sources: {
base: { type: 'raster', tiles: ['https://tiles.example.com/{z}/{x}/{y}.png'], tileSize: 256 },
},
layers: [{ id: 'base', type: 'raster', source: 'base' }],
},
center: [37.6173, 55.7558], // [lng, lat]
zoom: 11,
});
}
Если тяжёлая зависимость нужна только при включённой опции, повторите приём location. Расширение уходит в post_rel, условие считается в PHP прямо в config.php, а загруженный бандл сам регистрируется там, где его ищет основной код.
БД: схема прежняя
install.sql и uninstall.sql заменены декларативными миграциями в install/migrations/ с теми же десятью таблицами, агентами и обработчиком ui:onUIFormInitialize. ALTER для работающих порталов нет. Разницу заметят только на PostgreSQL. На новых установках колонки LATITUDE и LONGITUDE получают decimal(8,6) и decimal(9,6) вместо decimal без точности, а удаление модуля теперь сносит и b_location_recent_address, которую старый pgsql/uninstall.sql оставлял.
Мелочи и находки
- Если раздел отметок открыли до первого GPS-фикса, карта строится на точке региона портала, но скрыта, пока не придёт
FIT_BOUNDSс непустыми границами. Скрытие работает при обоих движках, а мгновенный первый переход к настоящим координатам гарантирован только в MapLibre, потому что Leaflet принимаетduration: 0за отсутствие параметра. - Повторный
INIT_MAPвызываетdestroy()у прежней карты, раньше она продолжала жить в том же контейнере. - Лоадер на маркере теперь висит над иконкой абсолютно позиционированным блоком. Рамка иконки больше не растёт на 20 px, и точка привязки не уезжает.
- У маркеров и кластеров рядом со старым атрибутом
testIdпоявилсяdata-testid, так чтоgetByTestId()в Playwright находит их без своих селекторов.