add switchable borough boundary overlay
This commit is contained in:
parent
79c2a8f37f
commit
a6156d66a3
40
app/public/geometries/boroughs.geojson
Normal file
40
app/public/geometries/boroughs.geojson
Normal file
File diff suppressed because one or more lines are too long
@ -10,6 +10,9 @@ export const initialMapViewport: MapViewport = {
|
|||||||
|
|
||||||
export type MapTheme = 'light' | 'night';
|
export type MapTheme = 'light' | 'night';
|
||||||
|
|
||||||
|
export type BoroughEnablementState = 'enabled' | 'disabled';
|
||||||
|
|
||||||
|
|
||||||
export const mapBackgroundColor: Record<MapTheme, string> = {
|
export const mapBackgroundColor: Record<MapTheme, string> = {
|
||||||
light: '#F0EEEB',
|
light: '#F0EEEB',
|
||||||
night: '#162639'
|
night: '#162639'
|
||||||
|
37
app/src/frontend/map/borough-switcher.css
Normal file
37
app/src/frontend/map/borough-switcher.css
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
.borough-theme {
|
||||||
|
filter: grayscale(100%) invert(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.borough-theme {
|
||||||
|
filter: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.borough-switcher {
|
||||||
|
z-index: 1000;
|
||||||
|
position: absolute;
|
||||||
|
top: 117px;
|
||||||
|
right: 10px;
|
||||||
|
float: right;
|
||||||
|
background: white;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.borough-switcher .btn {
|
||||||
|
margin: 0;
|
||||||
|
min-width: 280px;
|
||||||
|
}
|
||||||
|
.borough-switcher.night .btn {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #343a40;
|
||||||
|
border-color: #343a40;
|
||||||
|
}
|
||||||
|
.borough-switcher.night .btn:hover {
|
||||||
|
color: #343a40;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: none;
|
||||||
|
border-color: #343a40;
|
||||||
|
}
|
||||||
|
@media (max-width: 990px){
|
||||||
|
.borough-switcher {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
19
app/src/frontend/map/borough-switcher.tsx
Normal file
19
app/src/frontend/map/borough-switcher.tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import './borough-switcher.css';
|
||||||
|
|
||||||
|
interface BoroughSwitcherProps {
|
||||||
|
currentDisplay: string;
|
||||||
|
onSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BoroughSwitcher: React.FC<BoroughSwitcherProps> = (props) => (
|
||||||
|
<form className={`borough-switcher ${props.currentDisplay}`} onSubmit={props.onSubmit}>
|
||||||
|
<button className="btn btn-outline btn-outline-dark"
|
||||||
|
type="submit">
|
||||||
|
Switch borough overlay ({(props.currentDisplay === 'enabled')? 'Enabled' : 'Disabled'})
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default BoroughSwitcher;
|
34
app/src/frontend/map/layers/borough-boundary-layer.tsx
Normal file
34
app/src/frontend/map/layers/borough-boundary-layer.tsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { GeoJsonObject } from 'geojson';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { GeoJSON } from 'react-leaflet';
|
||||||
|
import { BoroughEnablementState } from '../../config/map-config';
|
||||||
|
import { apiGet } from '../../apiHelpers';
|
||||||
|
|
||||||
|
export function BoroughBoundaryLayer({enablement}: {enablement: BoroughEnablementState}) {
|
||||||
|
const [boundaryGeojson, setBoundaryGeojson] = useState<GeoJsonObject>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
apiGet('/geometries/boroughs.geojson')
|
||||||
|
.then(data => setBoundaryGeojson(data as GeoJsonObject));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if(enablement == "enabled") {
|
||||||
|
return boundaryGeojson &&
|
||||||
|
<GeoJSON
|
||||||
|
data={boundaryGeojson}
|
||||||
|
style={{color: '#f00', fill: false, weight: 1}}
|
||||||
|
/* minNativeZoom={17}*/
|
||||||
|
/>;
|
||||||
|
} else if (enablement == "disabled") {
|
||||||
|
return <div></div>
|
||||||
|
// do not display anything
|
||||||
|
return boundaryGeojson &&
|
||||||
|
<GeoJSON
|
||||||
|
data={boundaryGeojson}
|
||||||
|
style={{color: '#0f0', fill: false, weight: 1}} />
|
||||||
|
} else {
|
||||||
|
return boundaryGeojson &&
|
||||||
|
<GeoJSON data={boundaryGeojson} style={{color: '#0f0', fill: true}}/>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,11 +8,12 @@ import { apiGet } from '../apiHelpers';
|
|||||||
import { HelpIcon } from '../components/icons';
|
import { HelpIcon } from '../components/icons';
|
||||||
import { categoryMapsConfig } from '../config/category-maps-config';
|
import { categoryMapsConfig } from '../config/category-maps-config';
|
||||||
import { Category } from '../config/categories-config';
|
import { Category } from '../config/categories-config';
|
||||||
import { initialMapViewport, mapBackgroundColor, MapTheme } from '../config/map-config';
|
import { initialMapViewport, mapBackgroundColor, MapTheme, BoroughEnablementState } from '../config/map-config';
|
||||||
import { Building } from '../models/building';
|
import { Building } from '../models/building';
|
||||||
|
|
||||||
import { CityBaseMapLayer } from './layers/city-base-map-layer';
|
import { CityBaseMapLayer } from './layers/city-base-map-layer';
|
||||||
import { CityBoundaryLayer } from './layers/city-boundary-layer';
|
import { CityBoundaryLayer } from './layers/city-boundary-layer';
|
||||||
|
import { BoroughBoundaryLayer } from './layers/borough-boundary-layer';
|
||||||
import { BuildingBaseLayer } from './layers/building-base-layer';
|
import { BuildingBaseLayer } from './layers/building-base-layer';
|
||||||
import { BuildingDataLayer } from './layers/building-data-layer';
|
import { BuildingDataLayer } from './layers/building-data-layer';
|
||||||
import { BuildingNumbersLayer } from './layers/building-numbers-layer';
|
import { BuildingNumbersLayer } from './layers/building-numbers-layer';
|
||||||
@ -21,6 +22,7 @@ import { BuildingHighlightLayer } from './layers/building-highlight-layer';
|
|||||||
import { Legend } from './legend';
|
import { Legend } from './legend';
|
||||||
import SearchBox from './search-box';
|
import SearchBox from './search-box';
|
||||||
import ThemeSwitcher from './theme-switcher';
|
import ThemeSwitcher from './theme-switcher';
|
||||||
|
import BoroughSwitcher from './borough-switcher';
|
||||||
import { BuildingMapTileset } from '../config/tileserver-config';
|
import { BuildingMapTileset } from '../config/tileserver-config';
|
||||||
|
|
||||||
interface ColouringMapProps {
|
interface ColouringMapProps {
|
||||||
@ -41,6 +43,7 @@ export const ColouringMap : FC<ColouringMapProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
const [theme, setTheme] = useState<MapTheme>('night');
|
const [theme, setTheme] = useState<MapTheme>('night');
|
||||||
|
const [borough, setBorough] = useState<BoroughEnablementState>('disabled');
|
||||||
const [position, setPosition] = useState(initialMapViewport.position);
|
const [position, setPosition] = useState(initialMapViewport.position);
|
||||||
const [zoom, setZoom] = useState(initialMapViewport.zoom);
|
const [zoom, setZoom] = useState(initialMapViewport.zoom);
|
||||||
|
|
||||||
@ -73,6 +76,15 @@ export const ColouringMap : FC<ColouringMapProps> = ({
|
|||||||
[theme],
|
[theme],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const boroughSwitch = useCallback(
|
||||||
|
(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const newBorough = (borough === 'enabled')? 'disabled' : 'enabled';
|
||||||
|
setBorough(newBorough);
|
||||||
|
},
|
||||||
|
[borough],
|
||||||
|
)
|
||||||
|
|
||||||
const categoryMapDefinitions = useMemo(() => categoryMapsConfig[category], [category]);
|
const categoryMapDefinitions = useMemo(() => categoryMapsConfig[category], [category]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -121,6 +133,8 @@ export const ColouringMap : FC<ColouringMapProps> = ({
|
|||||||
style={{zIndex: 300}}
|
style={{zIndex: 300}}
|
||||||
>
|
>
|
||||||
<CityBoundaryLayer />
|
<CityBoundaryLayer />
|
||||||
|
<BoroughBoundaryLayer enablement={borough}/>
|
||||||
|
{ /*borough=="enabled" ? <BoroughBoundaryLayer enablement={borough}/> : <BoroughBoundaryLayer enablement={borough} /> */ }
|
||||||
<BuildingNumbersLayer revisionId={revisionId} />
|
<BuildingNumbersLayer revisionId={revisionId} />
|
||||||
{
|
{
|
||||||
selectedBuildingId &&
|
selectedBuildingId &&
|
||||||
@ -145,6 +159,7 @@ export const ColouringMap : FC<ColouringMapProps> = ({
|
|||||||
}
|
}
|
||||||
<Legend mapColourScaleDefinitions={categoryMapDefinitions} mapColourScale={mapColourScale} onMapColourScale={setMapColourScale}/>
|
<Legend mapColourScaleDefinitions={categoryMapDefinitions} mapColourScale={mapColourScale} onMapColourScale={setMapColourScale}/>
|
||||||
<ThemeSwitcher onSubmit={themeSwitch} currentTheme={theme} />
|
<ThemeSwitcher onSubmit={themeSwitch} currentTheme={theme} />
|
||||||
|
<BoroughSwitcher onSubmit={boroughSwitch} currentDisplay={borough} />
|
||||||
<SearchBox onLocate={handleLocate} />
|
<SearchBox onLocate={handleLocate} />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
}
|
}
|
||||||
.theme-switcher .btn {
|
.theme-switcher .btn {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
min-width: 280px;
|
||||||
}
|
}
|
||||||
.theme-switcher.night .btn {
|
.theme-switcher.night .btn {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
Loading…
Reference in New Issue
Block a user