diff --git a/docs/sources/visualizations/geomap.md b/docs/sources/visualizations/geomap.md index 26f4cee798f..fbc73c44852 100644 --- a/docs/sources/visualizations/geomap.md +++ b/docs/sources/visualizations/geomap.md @@ -23,7 +23,7 @@ The initial view configures how the GeoMap panel renders when the panel is first - **View** sets the center for the map when the panel first loads. - **Latitude** (available when the **View** mode is _Coordinates_) - **Longitude** (available when the **View** mode is _Coordinates_) -- **Zoom** sets the initial zoom level for the GeoMap panel. +- **Zoom** sets the initial zoom level for the GeoMap panel, or the initial maximum zoom level in case the _Fit data layers_ view is selected. ## Data layer diff --git a/public/app/plugins/panel/geomap/GeomapPanel.tsx b/public/app/plugins/panel/geomap/GeomapPanel.tsx index e1c2faf0f28..cbd6febaa7f 100644 --- a/public/app/plugins/panel/geomap/GeomapPanel.tsx +++ b/public/app/plugins/panel/geomap/GeomapPanel.tsx @@ -1,10 +1,13 @@ import React, { Component, ReactNode } from 'react'; import { DEFAULT_BASEMAP_CONFIG, geomapLayerRegistry } from './layers/registry'; -import { Map as OpenLayersMap, MapBrowserEvent, PluggableMap, View } from 'ol'; +import { Collection, Map as OpenLayersMap, MapBrowserEvent, PluggableMap, View } from 'ol'; import Attribution from 'ol/control/Attribution'; import Zoom from 'ol/control/Zoom'; import ScaleLine from 'ol/control/ScaleLine'; +import { createEmpty, extend, isEmpty } from 'ol/extent'; import { defaults as interactionDefaults } from 'ol/interaction'; +import BaseLayer from 'ol/layer/Base'; +import VectorLayer from 'ol/layer/Vector'; import MouseWheelZoom from 'ol/interaction/MouseWheelZoom'; import { @@ -219,7 +222,7 @@ export class GeomapPanel extends Component { if (options.view !== oldOptions.view) { console.log('View changed'); - this.map!.setView(this.initMapView(options.view)); + this.map!.setView(this.initMapView(options.view, this.map!.getLayers())); } if (options.controls !== oldOptions.controls) { @@ -252,7 +255,7 @@ export class GeomapPanel extends Component { const { options } = this.props; const map = (this.map = new OpenLayersMap({ - view: this.initMapView(options.view), + view: this.initMapView(options.view, undefined), pixelRatio: 1, // or zoom? layers: [], // loaded explicitly below controls: [], @@ -282,6 +285,7 @@ export class GeomapPanel extends Component { } this.layers = layers; this.map = map; // redundant + this.initViewExtent(map.getView(), options.view, map.getLayers()); this.mouseWheelZoom = new MouseWheelZoom(); this.map.addInteraction(this.mouseWheelZoom); @@ -497,7 +501,7 @@ export class GeomapPanel extends Component { return state; } - initMapView(config: MapViewConfig): View { + initMapView(config: MapViewConfig, layers?: Collection): View { let view = new View({ center: [0, 0], zoom: 1, @@ -512,13 +516,31 @@ export class GeomapPanel extends Component { view = sharedView; } } + if (layers) { + this.initViewExtent(view, config, layers); + } + return view; + } + initViewExtent(view: View, config: MapViewConfig, layers: Collection) { const v = centerPointRegistry.getIfExists(config.id); if (v) { let coord: Coordinate | undefined = undefined; if (v.lat == null) { if (v.id === MapCenterID.Coordinates) { coord = [config.lon ?? 0, config.lat ?? 0]; + } else if (v.id === MapCenterID.Fit) { + var extent = layers + .getArray() + .filter((l) => l instanceof VectorLayer) + .map((l) => (l as VectorLayer).getSource().getExtent() ?? []) + .reduce(extend, createEmpty()); + if (!isEmpty(extent)) { + view.fit(extent, { + padding: [30, 30, 30, 30], + maxZoom: config.zoom ?? config.maxZoom, + }); + } } else { console.log('TODO, view requires special handling', v); } @@ -536,10 +558,9 @@ export class GeomapPanel extends Component { if (config.minZoom) { view.setMaxZoom(config.minZoom); } - if (config.zoom) { + if (config.zoom && v?.id !== MapCenterID.Fit) { view.setZoom(config.zoom); } - return view; } initControls(options: ControlsOptions) { diff --git a/public/app/plugins/panel/geomap/view.ts b/public/app/plugins/panel/geomap/view.ts index 1f25d0cbdb1..e73a7efbeec 100644 --- a/public/app/plugins/panel/geomap/view.ts +++ b/public/app/plugins/panel/geomap/view.ts @@ -9,9 +9,15 @@ interface MapCenterItems extends RegistryItem { export enum MapCenterID { Zero = 'zero', Coordinates = 'coords', + Fit = 'fit', } export const centerPointRegistry = new Registry(() => [ + { + id: MapCenterID.Fit as string, + name: 'Fit data layers', + zoom: 15, // max zoom + }, { id: MapCenterID.Zero as string, name: '(0°, 0°)',