feat(bikeshare): render GBFS stations on Navara

This commit is contained in:
German Khokhlov committed 2026-10-28 13:12:19 +04:00
1 parent 1a694baf5a
commit d82a6f1550
32 files changed
+1394 -278

No files matched your search

+50 -14
View File
@@ -1,40 +1,76 @@
import { createIngestion } from './ingestion.js';
import { createModel } from './model.js';
import { createViewport } from './viewport.js';
import { createRendering } from './rendering.js';
import { createSelection } from './selection.js';
import { createQueries } from './queries.js';
import { createTesting } from './testing.js';
import { createControls } from './controls.js';
import { createLifecycle } from './lifecycle.js';
import { createState } from './state.js';
import { createBikeshareSelectedOverlayEntry } from './selectionModel.js';
/** Construct one layer with its own scene state and supplied application services. */
export function createBikeshareLayer({ services, source }) {
export function createBikeshareLayer({ services, source, rendererFactory }) {
if (typeof source?.getStations !== 'function')
throw new TypeError('A bikeshare source is required');
if (typeof rendererFactory !== 'function')
throw new TypeError('A bikeshare renderer factory is required');
const state = createState({ services });
const parts = {};
const context = { state, services, parts, source };
parts.ingestion = createIngestion(context);
parts.model = createModel(context);
parts.viewport = createViewport(context);
parts.rendering = createRendering(context);
parts.selection = createSelection(context);
parts.queries = createQueries(context);
parts.testing = createTesting(context);
parts.controls = createControls(context);
parts.lifecycle = createLifecycle(context);
let renderer = null;
let initialized = false;
const lifecycle = {
init(viewer, options = {}) {
if (initialized)
throw new Error('Bikeshare layer is already initialized');
renderer ??= rendererFactory({
...context,
viewer,
engine: options.engine ?? null,
});
if (!renderer?.lifecycle?.methods)
throw new Error('Bikeshare renderer is unavailable');
Object.assign(parts, renderer);
initialized = true;
try {
return renderer.lifecycle.methods.init(viewer, options);
} catch (error) {
initialized = false;
throw error;
}
},
enable(...args) {
return renderer?.lifecycle.methods.enable(...args);
},
disable(...args) {
return renderer?.lifecycle.methods.disable(...args);
},
destroy(...args) {
try {
return renderer?.lifecycle.methods.destroy(...args);
} finally {
renderer = null;
initialized = false;
for (const key of ['rendering', 'selection', 'viewport', 'lifecycle'])
delete parts[key];
}
},
};
return Object.assign(
{},
parts.controls.methods,
parts.lifecycle.methods,
lifecycle,
parts.ingestion?.methods,
{
createBikeshareSelectedOverlayEntry:
parts.selection.createBikeshareSelectedOverlayEntry,
_setBikeshareSelectionStateForTest:
parts.testing._setBikeshareSelectionStateForTest,
createBikeshareSelectedOverlayEntry,
_setBikeshareSelectionStateForTest: (options) => {
renderer ??= rendererFactory({ ...context, viewer: options.viewer });
Object.assign(parts, renderer);
parts.testing._setBikeshareSelectionStateForTest(options);
},
_selectBikeshareStationForTest:
parts.testing._selectBikeshareStationForTest,
_clearBikeshareSelectionForTest: