feat: Map component API and docs improvements
This commit is contained in:
@@ -2,6 +2,7 @@ import { CSSProperties, useEffect, useState } from 'react';
|
|||||||
import LoadingSpinner from './LoadingSpinner';
|
import LoadingSpinner from './LoadingSpinner';
|
||||||
import loadData from '../lib/loadData';
|
import loadData from '../lib/loadData';
|
||||||
import chroma from 'chroma-js';
|
import chroma from 'chroma-js';
|
||||||
|
import { GeospatialData } from '../types/properties';
|
||||||
import {
|
import {
|
||||||
MapContainer,
|
MapContainer,
|
||||||
TileLayer,
|
TileLayer,
|
||||||
@@ -14,26 +15,25 @@ import * as L from 'leaflet';
|
|||||||
|
|
||||||
export type MapProps = {
|
export type MapProps = {
|
||||||
layers: {
|
layers: {
|
||||||
data: string | GeoJSON.GeoJSON;
|
data: GeospatialData;
|
||||||
name: string;
|
name: string;
|
||||||
colorScale?: {
|
colorScale?: {
|
||||||
starting: string;
|
starting: string;
|
||||||
ending: string;
|
ending: string;
|
||||||
};
|
};
|
||||||
tooltip?:
|
tooltip?:
|
||||||
| {
|
| {
|
||||||
propNames: string[];
|
propNames: string[];
|
||||||
}
|
}
|
||||||
| boolean;
|
| boolean;
|
||||||
_id?: number;
|
|
||||||
}[];
|
}[];
|
||||||
title?: string;
|
title?: string;
|
||||||
center?: { latitude: number | undefined; longitude: number | undefined };
|
center?: { latitude: number | undefined; longitude: number | undefined };
|
||||||
zoom?: number;
|
zoom?: number;
|
||||||
style?: CSSProperties;
|
style?: CSSProperties;
|
||||||
autoZoomConfiguration?: {
|
autoZoomConfiguration?: {
|
||||||
layerName: string
|
layerName: string;
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Map({
|
export function Map({
|
||||||
@@ -56,17 +56,19 @@ export function Map({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadDataPromises = layers.map(async (layer) => {
|
const loadDataPromises = layers.map(async (layer) => {
|
||||||
|
const url = layer.data.url;
|
||||||
|
const geojson = layer.data.geojson;
|
||||||
let layerData: any;
|
let layerData: any;
|
||||||
|
|
||||||
if (typeof layer.data === 'string') {
|
if (url) {
|
||||||
// If "data" is string, assume it's a URL
|
// If "data" is string, assume it's a URL
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
layerData = await loadData(layer.data).then((res: any) => {
|
layerData = await loadData(url).then((res: any) => {
|
||||||
return JSON.parse(res);
|
return JSON.parse(res);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Else, expect raw GeoJSON
|
// Else, expect raw GeoJSON
|
||||||
layerData = layer.data;
|
layerData = geojson;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layer.colorScale) {
|
if (layer.colorScale) {
|
||||||
@@ -111,23 +113,23 @@ export function Map({
|
|||||||
// Create the title box
|
// Create the title box
|
||||||
var info = new L.Control() as any;
|
var info = new L.Control() as any;
|
||||||
|
|
||||||
info.onAdd = function() {
|
info.onAdd = function () {
|
||||||
this._div = L.DomUtil.create('div', 'info');
|
this._div = L.DomUtil.create('div', 'info');
|
||||||
this.update();
|
this.update();
|
||||||
return this._div;
|
return this._div;
|
||||||
};
|
};
|
||||||
|
|
||||||
info.update = function() {
|
info.update = function () {
|
||||||
this._div.innerHTML = `<h4 style="font-weight: 600; background: #f9f9f9; padding: 5px; border-radius: 5px; color: #464646;">${title}</h4>`;
|
this._div.innerHTML = `<h4 style="font-weight: 600; background: #f9f9f9; padding: 5px; border-radius: 5px; color: #464646;">${title}</h4>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (title) info.addTo(map.target);
|
if (title) info.addTo(map.target);
|
||||||
if(!autoZoomConfiguration) return;
|
if (!autoZoomConfiguration) return;
|
||||||
|
|
||||||
let layerToZoomBounds = L.latLngBounds(L.latLng(0, 0), L.latLng(0, 0));
|
let layerToZoomBounds = L.latLngBounds(L.latLng(0, 0), L.latLng(0, 0));
|
||||||
|
|
||||||
layers.forEach((layer) => {
|
layers.forEach((layer) => {
|
||||||
if(layer.name === autoZoomConfiguration.layerName) {
|
if (layer.name === autoZoomConfiguration.layerName) {
|
||||||
const data = layersData.find(
|
const data = layersData.find(
|
||||||
(layerData) => layerData.name === layer.name
|
(layerData) => layerData.name === layer.name
|
||||||
)?.data;
|
)?.data;
|
||||||
|
|||||||
@@ -4,8 +4,15 @@
|
|||||||
* Based on vega.
|
* Based on vega.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
type URL = string; // Just in case we want to transform it into an object with configurations
|
||||||
export interface Data {
|
export interface Data {
|
||||||
url?: string;
|
url?: URL;
|
||||||
values?: { [key: string]: number | string }[];
|
values?: { [key: string]: number | string }[];
|
||||||
csv?: string;
|
csv?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GeospatialData {
|
||||||
|
url?: URL;
|
||||||
|
geojson?: GeoJSON.GeoJSON;
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ const meta: Meta = {
|
|||||||
argTypes: {
|
argTypes: {
|
||||||
layers: {
|
layers: {
|
||||||
description:
|
description:
|
||||||
'Data to be displayed.\n\n GeoJSON Object \n\nOR\n\n URL to GeoJSON Object',
|
'Array of layers to be displayed on the map. Should be an object with: \n\n \
|
||||||
|
`data`: object with either a `url` property pointing to a GeoJSON file or a `geojson` property with a GeoJSON object. \n\n \
|
||||||
|
`name`: name of the layer. \n\n \
|
||||||
|
`colorscale`: object with a `starting` and `ending` colors that will be used to create a gradient and color the map. \n\n \
|
||||||
|
`tooltip`: `true` to show all available features on the tooltip, object with a `propNames` property as an array of strings to choose which features to display. \n\n',
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
description: 'Title to display on the map.',
|
description: 'Title to display on the map.',
|
||||||
@@ -19,14 +23,15 @@ const meta: Meta = {
|
|||||||
description: 'Initial coordinates of the center of the map',
|
description: 'Initial coordinates of the center of the map',
|
||||||
},
|
},
|
||||||
zoom: {
|
zoom: {
|
||||||
description: 'Zoom level',
|
description: 'Initial zoom level',
|
||||||
},
|
},
|
||||||
style: {
|
style: {
|
||||||
description: "Styles for the container"
|
description: "CSS styles to be applied to the map's container.",
|
||||||
},
|
},
|
||||||
autoZoomConfiguration: {
|
autoZoomConfiguration: {
|
||||||
description: "Configuration to auto zoom in the specified layer data"
|
description:
|
||||||
}
|
"Pass a layer's name to automatically zoom to the bounding area of a layer.",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -40,7 +45,9 @@ export const GeoJSONPolygons: Story = {
|
|||||||
args: {
|
args: {
|
||||||
layers: [
|
layers: [
|
||||||
{
|
{
|
||||||
data: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson',
|
data: {
|
||||||
|
url: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson',
|
||||||
|
},
|
||||||
name: 'Polygons',
|
name: 'Polygons',
|
||||||
tooltip: { propNames: ['name'] },
|
tooltip: { propNames: ['name'] },
|
||||||
colorScale: {
|
colorScale: {
|
||||||
@@ -60,7 +67,9 @@ export const GeoJSONPoints: Story = {
|
|||||||
args: {
|
args: {
|
||||||
layers: [
|
layers: [
|
||||||
{
|
{
|
||||||
data: 'https://opendata.arcgis.com/datasets/9c58741995174fbcb017cf46c8a42f4b_25.geojson',
|
data: {
|
||||||
|
url: 'https://opendata.arcgis.com/datasets/9c58741995174fbcb017cf46c8a42f4b_25.geojson',
|
||||||
|
},
|
||||||
name: 'Points',
|
name: 'Points',
|
||||||
tooltip: { propNames: ['Location'] },
|
tooltip: { propNames: ['Location'] },
|
||||||
},
|
},
|
||||||
@@ -76,12 +85,16 @@ export const GeoJSONMultipleLayers: Story = {
|
|||||||
args: {
|
args: {
|
||||||
layers: [
|
layers: [
|
||||||
{
|
{
|
||||||
data: 'https://opendata.arcgis.com/datasets/9c58741995174fbcb017cf46c8a42f4b_25.geojson',
|
data: {
|
||||||
|
url: 'https://opendata.arcgis.com/datasets/9c58741995174fbcb017cf46c8a42f4b_25.geojson',
|
||||||
|
},
|
||||||
name: 'Points',
|
name: 'Points',
|
||||||
tooltip: true,
|
tooltip: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
data: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson',
|
data: {
|
||||||
|
url: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson',
|
||||||
|
},
|
||||||
name: 'Polygons',
|
name: 'Polygons',
|
||||||
tooltip: true,
|
tooltip: true,
|
||||||
colorScale: {
|
colorScale: {
|
||||||
@@ -94,19 +107,23 @@ export const GeoJSONMultipleLayers: Story = {
|
|||||||
center: { latitude: 45, longitude: 0 },
|
center: { latitude: 45, longitude: 0 },
|
||||||
zoom: 2,
|
zoom: 2,
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
export const GeoJSONMultipleLayersWithAutoZoomInSpecifiedLayer: Story = {
|
export const GeoJSONMultipleLayersWithAutoZoomInSpecifiedLayer: Story = {
|
||||||
name: 'GeoJSON polygons and points map with auto zoom in the points layer',
|
name: 'GeoJSON polygons and points map with auto zoom in the points layer',
|
||||||
args: {
|
args: {
|
||||||
layers: [
|
layers: [
|
||||||
{
|
{
|
||||||
data: 'https://opendata.arcgis.com/datasets/9c58741995174fbcb017cf46c8a42f4b_25.geojson',
|
data: {
|
||||||
|
url: 'https://opendata.arcgis.com/datasets/9c58741995174fbcb017cf46c8a42f4b_25.geojson',
|
||||||
|
},
|
||||||
name: 'Points',
|
name: 'Points',
|
||||||
tooltip: true,
|
tooltip: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
data: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson',
|
data: {
|
||||||
|
url: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson',
|
||||||
|
},
|
||||||
name: 'Polygons',
|
name: 'Polygons',
|
||||||
tooltip: true,
|
tooltip: true,
|
||||||
colorScale: {
|
colorScale: {
|
||||||
@@ -119,7 +136,7 @@ export const GeoJSONMultipleLayersWithAutoZoomInSpecifiedLayer: Story = {
|
|||||||
center: { latitude: 45, longitude: 0 },
|
center: { latitude: 45, longitude: 0 },
|
||||||
zoom: 2,
|
zoom: 2,
|
||||||
autoZoomConfiguration: {
|
autoZoomConfiguration: {
|
||||||
layerName: 'Points'
|
layerName: 'Points',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user