proof of concept for borough names with Mapnik-based tiles
This commit is contained in:
parent
838a0dd087
commit
c4933fdc11
@ -24,6 +24,11 @@
|
|||||||
<MinScaleDenominator>0</MinScaleDenominator>
|
<MinScaleDenominator>0</MinScaleDenominator>
|
||||||
</Rule>
|
</Rule>
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style name="base_boroughs">
|
||||||
|
<Rule>
|
||||||
|
<TextSymbolizer size="24" fill="#f99" face-name="DejaVu Sans Bold Oblique" halo-radius="1" wrap-width="20">[name]</TextSymbolizer>
|
||||||
|
</Rule>
|
||||||
|
</Style>
|
||||||
<Style name="number_labels">
|
<Style name="number_labels">
|
||||||
<Rule>
|
<Rule>
|
||||||
<TextSymbolizer
|
<TextSymbolizer
|
||||||
|
@ -8,12 +8,13 @@ export const initialMapViewport: MapViewport = {
|
|||||||
zoom: 16,
|
zoom: 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MapTheme = 'light' | 'night' | 'night_outlines';
|
export type MapTheme = 'light' | 'night' | 'night_outlines' | 'boroughs';
|
||||||
|
|
||||||
export type LayerEnablementState = 'enabled' | 'disabled';
|
export type LayerEnablementState = 'enabled' | 'disabled';
|
||||||
|
|
||||||
export const mapBackgroundColor: Record<MapTheme, string> = {
|
export const mapBackgroundColor: Record<MapTheme, string> = {
|
||||||
light: '#F0EEEB',
|
light: '#F0EEEB',
|
||||||
night: '#162639',
|
night: '#162639',
|
||||||
night_outlines: '#162639'
|
night_outlines: '#162639',
|
||||||
|
boroughs: '#ff0000',
|
||||||
};
|
};
|
||||||
|
@ -21,6 +21,6 @@ export type BuildingMapTileset = 'date_year' |
|
|||||||
'dynamics_demolished_count' |
|
'dynamics_demolished_count' |
|
||||||
'team';
|
'team';
|
||||||
|
|
||||||
export type SpecialMapTileset = 'base_light' | 'base_night' | 'base_night_outlines' | 'highlight' | 'number_labels';
|
export type SpecialMapTileset = 'base_light' | 'base_night' | 'base_night_outlines' | 'highlight' | 'number_labels' | 'base_boroughs';
|
||||||
|
|
||||||
export type MapTileset = BuildingMapTileset | SpecialMapTileset;
|
export type MapTileset = BuildingMapTileset | SpecialMapTileset;
|
||||||
|
@ -3,6 +3,7 @@ import React, { useEffect, useState } from 'react';
|
|||||||
import { GeoJSON } from 'react-leaflet';
|
import { GeoJSON } from 'react-leaflet';
|
||||||
import { useDisplayPreferences } from '../../displayPreferences-context';
|
import { useDisplayPreferences } from '../../displayPreferences-context';
|
||||||
import { apiGet } from '../../apiHelpers';
|
import { apiGet } from '../../apiHelpers';
|
||||||
|
import { BuildingBaseLayerAllZoom } from './building-base-layer-all-zoom';
|
||||||
|
|
||||||
export function BoroughBoundaryLayer({}) {
|
export function BoroughBoundaryLayer({}) {
|
||||||
const [boundaryGeojson, setBoundaryGeojson] = useState<GeoJsonObject>(null);
|
const [boundaryGeojson, setBoundaryGeojson] = useState<GeoJsonObject>(null);
|
||||||
@ -15,12 +16,12 @@ export function BoroughBoundaryLayer({}) {
|
|||||||
|
|
||||||
if(borough == "enabled") {
|
if(borough == "enabled") {
|
||||||
return boundaryGeojson &&
|
return boundaryGeojson &&
|
||||||
<GeoJSON
|
<><GeoJSON
|
||||||
attribution='Borough boundary from <a href=https://data.london.gov.uk/dataset/london_boroughs>London Datastore</a> Ordnance Survey Open Data - Contains public sector information licensed under the <a href=https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/>Open Government Licence v3.0</a>'
|
attribution='Borough boundary from <a href=https://data.london.gov.uk/dataset/london_boroughs>London Datastore</a> Ordnance Survey Open Data - Contains public sector information licensed under the <a href=https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/>Open Government Licence v3.0</a>'
|
||||||
data={boundaryGeojson}
|
data={boundaryGeojson}
|
||||||
style={{color: '#f00', fill: false, weight: 1}}
|
style={{color: '#f00', fill: false, weight: 1}}
|
||||||
/* minNativeZoom={17}*/
|
/* minNativeZoom={17}*/
|
||||||
/>;
|
/><BuildingBaseLayerAllZoom theme="boroughs" /></>;
|
||||||
} else if (borough == "disabled") {
|
} else if (borough == "disabled") {
|
||||||
return <div></div>
|
return <div></div>
|
||||||
// do not display anything
|
// do not display anything
|
||||||
|
19
app/src/frontend/map/layers/building-base-layer-all-zoom.tsx
Normal file
19
app/src/frontend/map/layers/building-base-layer-all-zoom.tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { TileLayer } from 'react-leaflet';
|
||||||
|
|
||||||
|
import { MapTheme } from '../../config/map-config';
|
||||||
|
import { MapTileset } from '../../config/tileserver-config';
|
||||||
|
|
||||||
|
import {getTileLayerUrl } from './get-tile-layer-url';
|
||||||
|
|
||||||
|
export function BuildingBaseLayerAllZoom({ theme }: {theme: MapTheme}) {
|
||||||
|
const tileset = `base_${theme}` as const;
|
||||||
|
|
||||||
|
return <TileLayer
|
||||||
|
key={theme} /* needed because TileLayer url is not mutable in react-leaflet v3 */
|
||||||
|
url={getTileLayerUrl(tileset)}
|
||||||
|
minZoom={1}
|
||||||
|
maxZoom={109}
|
||||||
|
detectRetina={true}
|
||||||
|
/>;
|
||||||
|
}
|
@ -18,6 +18,12 @@ const LAYER_QUERIES = {
|
|||||||
geometry_id
|
geometry_id
|
||||||
FROM
|
FROM
|
||||||
buildings`,
|
buildings`,
|
||||||
|
base_boroughs: `
|
||||||
|
SELECT
|
||||||
|
geometry_id,
|
||||||
|
name
|
||||||
|
FROM
|
||||||
|
external_data_borough_boundary`,
|
||||||
number_labels:`
|
number_labels:`
|
||||||
SELECT
|
SELECT
|
||||||
geometry_id,
|
geometry_id,
|
||||||
@ -245,6 +251,29 @@ function getDataConfig(tileset: string): DataConfig {
|
|||||||
throw new Error('Invalid tileset requested');
|
throw new Error('Invalid tileset requested');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(tileset == 'base_boroughs') {
|
||||||
|
const query = `(
|
||||||
|
SELECT
|
||||||
|
d.*,
|
||||||
|
g.geometry_geom
|
||||||
|
FROM (
|
||||||
|
${table}
|
||||||
|
) AS d
|
||||||
|
JOIN
|
||||||
|
geometries AS g
|
||||||
|
ON d.geometry_id = g.geometry_id
|
||||||
|
JOIN
|
||||||
|
external_data_borough_boundary AS b
|
||||||
|
ON d.geometry_id = b.geometry_id
|
||||||
|
) AS data
|
||||||
|
`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
geometry_field: GEOMETRY_FIELD,
|
||||||
|
table: query
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const query = `(
|
const query = `(
|
||||||
SELECT
|
SELECT
|
||||||
d.*,
|
d.*,
|
||||||
|
1
migrations/036.borough_borders_and_labels.down.sql
Normal file
1
migrations/036.borough_borders_and_labels.down.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
DROP TABLE IF EXISTS external_data_borough_boundary;
|
8
migrations/036.borough_borders_and_labels.up.sql
Normal file
8
migrations/036.borough_borders_and_labels.up.sql
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS external_data_borough_boundary (
|
||||||
|
-- internal unique id
|
||||||
|
planning_entry_id serial PRIMARY KEY,
|
||||||
|
|
||||||
|
-- geometry as EPSG:3857 avoiding reprojection for tiles
|
||||||
|
geometry_id integer REFERENCES geometries,
|
||||||
|
name VARCHAR(50)
|
||||||
|
);
|
Loading…
Reference in New Issue
Block a user