@gooddata/react-components
Version:
GoodData.UI - A powerful JavaScript library for building analytical applications
94 lines (82 loc) • 2.67 kB
text/typescript
// (C) 2020 GoodData Corporation
import get = require("lodash/get");
import mapboxgl = require("mapbox-gl");
import { DEFAULT_CENTER, DEFAULT_WORLD_BOUNDS, DEFAULT_ZOOM, VIEWPORTS } from "../../constants/geoChart";
import { IGeoConfig, IGeoConfigViewport, IGeoLngLat, IGeoLngLatBounds } from "../../interfaces/GeoChart";
interface IGeoViewport {
bounds?: mapboxgl.LngLatBoundsLike;
center?: IGeoLngLat;
zoom?: number;
}
export function getViewportOptions(data: IGeoLngLat[], config: IGeoConfig): IGeoViewport {
const center: IGeoLngLat = get<IGeoConfig, "center">(config, "center");
const zoom: number = get<IGeoConfig, "zoom", number>(config, "zoom", DEFAULT_ZOOM);
const { area }: IGeoConfigViewport = get<IGeoConfig, "viewport", {}>(config, "viewport", {});
// use `center` config if it exists
if (!center) {
if (VIEWPORTS[area]) {
return {
bounds: VIEWPORTS[area],
};
} else {
const lngLatBounds: IGeoLngLatBounds = getLngLatBounds(data);
if (lngLatBounds) {
return {
bounds: [lngLatBounds.northEast, lngLatBounds.southWest],
};
}
return {
center: DEFAULT_CENTER,
zoom,
};
}
}
return {
center,
zoom,
};
}
/*
* @method getLngLatBounds: IGeoLngLatBounds
* Represents a rectangular geographical area on a map.
*
* @example
*
* ```js
* const corner1 = [40.712, -74.227],
* const corner2 = [40.774, -74.125],
* const bounds = getLngLatBounds([corner1, corner2]);
*
* bounds && map.fitBounds([bounds.northEast, bounds.southWest], { padding: 60 });
* ```
*/
export function getLngLatBounds(lnglats: IGeoLngLat[]): IGeoLngLatBounds {
if (!lnglats || !lnglats.length) {
return;
}
return lnglats.reduce(extendLngLatBounds, undefined) || DEFAULT_WORLD_BOUNDS;
}
// @method extendLngLatBounds: IGeoLngLatBounds
// Extend the bounds to contain the given point
function extendLngLatBounds(bounds: IGeoLngLatBounds, lnglat: IGeoLngLat): IGeoLngLatBounds {
if (!lnglat) {
return bounds;
}
if (!bounds) {
return {
northEast: lnglat,
southWest: lnglat,
};
}
const { northEast, southWest } = bounds;
return {
northEast: {
lat: Math.max(lnglat.lat, northEast.lat),
lng: Math.max(lnglat.lng, northEast.lng),
},
southWest: {
lat: Math.min(lnglat.lat, southWest.lat),
lng: Math.min(lnglat.lng, southWest.lng),
},
};
}