Контролы в Leaflet представляют собой расширяемые UI-компоненты
карты, реализованные через базовый класс L.Control. Их
жизненный цикл определяется последовательностью инициализации,
добавления на карту, реакции на изменение состояния карты и последующего
удаления. Вся архитектура построена вокруг предсказуемых хук-методов,
которые позволяют подключать пользовательскую логику в строго
определённые точки работы компонента.
Контрол в Leaflet создаётся через наследование:
L.Control.Custom = L.Control.extend({
initialize: function (options) {
L.Util.setOptions(this, options);
},
onAdd: function (map) {
const container = L.DomUtil.create('div', 'custom-control');
return container;
},
onRemove: function (map) {
// очистка ресурсов
}
});
Ключевым является тот факт, что контрол не добавляется напрямую в DOM — его жизненный цикл управляется картой.
Метод initialize выполняется в момент создания
экземпляра контролa.
Основные задачи:
initialize: function (options) {
L.Util.setOptions(this, options);
this._buttons = [];
}
Особенности:
onAdd(map) — центральная точка жизненного цикла,
вызываемая при добавлении контрола на карту.
onAdd: function (map) {
this._map = map;
const container = L.DomUtil.create('div', 'leaflet-control-custom');
this._initLayout(container);
this._bindEvents();
return container;
}
Назначение метода:
Важно:
onRemove(map) вызывается при удалении контрола с
карты.
onRemove: function (map) {
this._unbindEvents();
this._map = null;
}
Функции метода:
Особенности:
Хотя addTo(map) не является методом, который
переопределяется, он играет ключевую роль в жизненном цикле.
control.addTo(map);
Внутренний механизм:
onAdd(map);Эквивалентный поток:
addTo(map)
→ onAdd(map)
→ DOM insertion
→ control added event
При добавлении контрола происходит связывание с объектом карты:
this._map получает ссылку на L.Map;Пример:
onAdd: function (map) {
this._map = map;
map.on('zoomend', this._update, this);
return this._container;
}
Критически важная часть жизненного цикла — корректное отсоединение от событий.
onRemove: function (map) {
map.off('zoomend', this._update, this);
}
Игнорирование этого шага приводит к:
В контролах часто используются вспомогательные методы, влияющие на поведение жизненного цикла:
Отвечает за построение DOM-структуры.
_initLayout: function () {
this._container = L.DomUtil.create('div', 'leaflet-control');
}
Вызывается внутри onAdd, но не является частью
публичного API.
Используется для обновления состояния UI в ответ на изменения карты.
_update: function () {
const zoom = this._map.getZoom();
this._container.innerHTML = zoom;
}
Для контролов с изменяемым положением:
_setPosition: function (position) {
L.DomUtil.removeClass(this._container, 'leaflet-top leaflet-bottom');
L.DomUtil.addClass(this._container, position);
}
Контролы могут генерировать и обрабатывать события:
add — после добавления на карту;remove — после удаления;Пример:
map.on('controladd', function (e) {
console.log(e.control);
});
Контрол может быть удалён и добавлен повторно:
map.removeControl(control);
map.addControl(control);
Поведение:
onRemove вызывается при удалении;onAdd;При проектировании контролов важно разделять:
Правильная архитектура:
initialize — конфигурация;onAdd — создание интерфейса;onRemove — очистка;Часто встречающиеся проблемы:
onAdd;map до onAdd;initialize;Типичный цикл контролa:
initialize(options)
↓
addTo(map)
↓
onAdd(map)
↓
[работа контролa]
↓
onRemove(map)
Этот порядок определяет всю модель поведения расширяемых UI-компонентов Leaflet и является основой для построения сложных интерфейсных элементов на карте.