В основе адаптивного поведения Kepler.gl лежит механизм динамического измерения контейнера, реализованный через компонент AutoSizer из экосистемы react-virtualized. Его задача заключается в постоянном отслеживании размеров родительского DOM-элемента и передаче актуальных значений ширины и высоты в компонент карты. Это позволяет визуализации занимать всё доступное пространство без ручного управления размерами.
Kepler.gl строит интерфейс вокруг идеи «карта как потоковый рендеринг внутри контейнера», где размеры не задаются жестко, а вычисляются в момент рендера и при каждом изменении layout.
AutoSizer использует наблюдение за изменениями размеров контейнера и обновляет параметры через React state/props механизм.
Основные этапы работы:
getBoundingClientRectwidth и
height в дочерний компонентКлючевой особенностью является реактивная модель: любое изменение контейнера приводит к повторному вычислению размеров и повторному рендеру вложенного компонента.
В Kepler.gl AutoSizer используется как обертка над основным компонентом карты. Он обеспечивает:
В типовой структуре Kepler.gl компонент выглядит следующим образом:
import KeplerGl from 'kepler.gl';
import AutoSizer from 'react-virtualized/dist/commonjs/AutoSizer';
const MapWrapper = () => (
<div style={{ height: '100vh', width: '100%' }}>
<AutoSizer>
{({ height, width }) => (
<KeplerGl
id="map"
width={width}
height={height}
/>
)}
</AutoSizer>
</div>
);
Здесь AutoSizer выступает источником «истины» по размерам контейнера.
Корректная работа AutoSizer зависит от цепочки родительских элементов. Если хотя бы один контейнер не имеет вычисляемой высоты, AutoSizer возвращает нулевые значения.
Типичная зависимость:
html, body должны иметь высоту 100%Пример корректной структуры:
html, body {
height: 100%;
margin: 0;
}
#root {
height: 100%;
display: flex;
}
Kepler.gl в таком окружении получает стабильные размеры и не «схлопывается» при инициализации.
AutoSizer отслеживает изменения окна и контейнера, что особенно важно для сценариев:
При каждом изменении инициируется пересчет, после чего Kepler.gl обновляет WebGL viewport:
AutoSizer наиболее стабильно работает в flex- и grid-контейнерах при соблюдении одного условия: родитель должен иметь ограниченную высоту.
Пример flex-раскладки:
.wrapper {
display: flex;
height: 100vh;
}
.sidebar {
width: 300px;
}
.mapContainer {
flex: 1;
position: relative;
}
<div className="wrapper">
<div className="sidebar" />
<div className="mapContainer">
<AutoSizer>
{({ width, height }) => (
<KeplerGl id="map" width={width} height={height} />
)}
</AutoSizer>
</div>
</div>
Такая структура обеспечивает предсказуемую геометрию без скачков интерфейса.
Kepler.gl использует WebGL для рендеринга, поэтому изменение размеров влияет не только на DOM, но и на графический контекст.
При обновлении размеров выполняются операции:
gl.viewport(0, 0, width, height)AutoSizer выступает триггером для синхронизации этих параметров.
Особое значение AutoSizer приобретает при наличии анимаций и динамических панелей:
Каждое изменение контейнера приводит к повторному измерению, что может вызывать частые ререндеры.
Для стабилизации поведения применяются:
Частые изменения размеров могут приводить к нагрузке на WebGL-контекст. Основные источники затрат:
Оптимизационные подходы:
will-change: transform для
контейнеровAutoSizer сам по себе легковесен, но становится критичным узлом в больших дашбордах.
Несмотря на универсальность, механизм имеет ряд особенностей:
display: noneВ условиях сложных интерфейсов иногда требуется ручное управление размерами вместо автоматического режима.
В server-side rendering AutoSizer не может вычислить реальные размеры DOM. В результате:
Типичная схема:
Это поведение является нормальным для всех DOM-based измерений.
AutoSizer интегрируется в жизненный цикл React через:
componentDidMount — первичное измерениеcomponentDidUpdate — реакция на изменения layoutwindow.resize listener — глобальные изменения
viewportВ функциональном стиле используется аналог через hooks внутри Kepler.gl, где AutoSizer передает значения через render props.
В крупных приложениях AutoSizer часто используется в сочетании с:
Распространённый паттерн — изоляция карты в отдельный контейнер, полностью управляемый AutoSizer, чтобы исключить влияние внешнего layout.
При изменении масштабирования браузера или DPI AutoSizer не всегда пересчитывает размеры напрямую, однако Kepler.gl реагирует через:
devicePixelRatioЭто обеспечивает сохранение четкости визуализации при масштабировании интерфейса.