make mapstyles simpler

This commit is contained in:
Paul Bienkowski 2021-11-29 18:34:58 +01:00
parent 15dfb2dc3b
commit 38b1b92210
3 changed files with 73 additions and 86 deletions

View file

@ -3,6 +3,8 @@ import _ from 'lodash'
import bright from './bright.json'
import positron from './positron.json'
export {bright, positron}
export function colorByDistance(attribute = 'distance_overtaker_mean', fallback = '#ABC') {
return [
'case',
@ -24,62 +26,58 @@ export function colorByDistance(attribute = 'distance_overtaker_mean', fallback
]
}
function addRoadsStyle(style, mapSource) {
style.sources.obs = mapSource
export const roadsLayer = {
id: 'obs',
type: 'line',
source: 'obs',
'source-layer': 'obs_roads',
layout: {
'line-cap': 'round',
'line-join': 'round',
},
paint: {
'line-width': [
'interpolate',
['exponential', 1.5],
['zoom'],
12,
2,
17,
['case', ['!', ['to-boolean', ['get', 'distance_overtaker_mean']]], 2, 6],
],
'line-color': colorByDistance(),
'line-opacity': [
'interpolate',
['linear'],
['zoom'],
12,
0,
13,
['case', ['!', ['to-boolean', ['get', 'distance_overtaker_mean']]], 0, 1],
14,
['case', ['!', ['to-boolean', ['get', 'distance_overtaker_mean']]], 0, 1],
15,
1,
],
'line-offset': [
'interpolate',
['exponential', 1.5],
['zoom'],
12,
['get', 'offset_direction'],
19,
['*', ['get', 'offset_direction'], 8],
],
},
minzoom: 12,
}
// insert before "road_oneway" layer
let idx = style.layers.findIndex((l) => l.id === 'road_oneway')
if (idx === -1) {
idx = style.layers.length
export const trackLayer = {
type: 'line',
paint: {
'line-width': ['interpolate', ['linear'], ['zoom'], 14, 2, 17, 5],
'line-color': '#F06292',
}
style.layers.splice(idx, 0, {
id: 'obs',
type: 'line',
source: 'obs',
'source-layer': 'obs_roads',
layout: {
'line-cap': 'round',
'line-join': 'round',
},
paint: {
'line-width': [
'interpolate',
['exponential', 1.5],
['zoom'],
12,
2,
17,
['case', ['!', ['to-boolean', ['get', 'distance_overtaker_mean']]], 2, 6],
],
'line-color': colorByDistance(),
'line-opacity': [
'interpolate',
['linear'],
['zoom'],
12,
0,
13,
['case', ['!', ['to-boolean', ['get', 'distance_overtaker_mean']]], 0, 1],
14,
['case', ['!', ['to-boolean', ['get', 'distance_overtaker_mean']]], 0, 1],
15,
1,
],
'line-offset': [
'interpolate',
['exponential', 1.5],
['zoom'],
12,
['get', 'offset_direction'],
19,
['*', ['get', 'offset_direction'], 8],
],
},
minzoom: 12,
})
return style
}
export const basemap = positron
export const obsRoads = (sourceUrl) => addRoadsStyle(_.cloneDeep(basemap), sourceUrl)

View file

@ -1,13 +1,14 @@
import React from 'react'
import ReactMapGl, {AttributionControl, NavigationControl, Layer, Source} from 'react-map-gl'
import {Page} from 'components'
import {useConfig, Config} from 'config'
import {useHistory, useLocation} from 'react-router-dom'
import ReactMapGl, {AttributionControl } from 'react-map-gl'
import styles from './MapPage.module.less'
import {obsRoads, basemap } from '../mapstyles'
import {roadsLayer, basemap} from '../mapstyles'
function parseHash(v) {
if (!v) return null
@ -37,52 +38,47 @@ function useViewportFromUrl() {
return [value || EMPTY_VIEWPORT, setter]
}
function CustomMapInner({viewportFromUrl, mapSource, config, mode, children}: {viewportFromUrl?: boolean, mapSource: string, config: Config, mode?: 'roads'}) {
const mapStyle = React.useMemo(() => {
if (mode === 'roads') {
return mapSource && obsRoads(mapSource)
} else {
return basemap
}
}, [mapSource, mode])
export function CustomMap({viewportFromUrl, children, boundsFromJson}: {viewportFromUrl?: boolean, children: React.ReactNode}) {
const [viewportState, setViewportState] = React.useState(EMPTY_VIEWPORT)
const [viewportUrl, setViewportUrl] = useViewportFromUrl()
const [viewport, setViewport] = viewportFromUrl ? [viewportUrl, setViewportUrl] : [viewportState, setViewportState]
const config = useConfig()
React.useEffect(() => {
if (config?.mapHome && viewport.zoom === 0) {
setViewport(config.mapHome)
}
}, [config])
if (!mapStyle) {
return null
}
return (
<ReactMapGl mapStyle={mapStyle} width="100%" height="100%" onViewportChange={setViewport} {...viewport}>
<ReactMapGl mapStyle={basemap} width="100%" height="100%" onViewportChange={setViewport} {...viewport}>
<AttributionControl style={{right: 0, bottom: 0}} customAttribution={[
'<a href="https://openstreetmap.org/copyright" target="_blank" rel="nofollow noopener noreferrer">© OpenStreetMap contributors</a>',
'<a href="https://openmaptiles.org/" target="_blank" rel="nofollow noopener noreferrer">© OpenMapTiles</a>',
'<a href="https://openbikesensor.org/" target="_blank" rel="nofollow noopener noreferrer">© OpenBikeSensor</a>',
]} />
<NavigationControl style={{left: 0, top: 0}} />
{children}
</ReactMapGl>
)
}
export function CustomMap(props) {
const config = useConfig() || {}
if (!config) return null;
const {obsMapSource: mapSource} = config
export function RoadsMap() {
const {obsMapSource} = useConfig() || {}
if (!mapSource) return null;
if (!obsMapSource) {
return null;
}
return (
<CustomMapInner {...{mapSource, config}} {...props} />
<CustomMap viewportFromUrl>
<Source id="obs" {...obsMapSource}>
<Layer {...roadsLayer} />
</Source>
</CustomMap>
)
}
@ -90,7 +86,7 @@ export default function MapPage() {
return (
<Page fullScreen>
<div className={styles.mapContainer}>
<CustomMap mode='roads' viewportFromUrl />
<RoadsMap />
</div>
</Page>
)

View file

@ -4,7 +4,7 @@ import {Source, Layer} from 'react-map-gl'
import type {TrackData} from 'types'
import {CustomMap} from '../MapPage'
import {colorByDistance} from '../../mapstyles'
import {colorByDistance, trackLayer} from '../../mapstyles'
export default function TrackMap({
trackData,
@ -27,14 +27,7 @@ export default function TrackMap({
<CustomMap>
{showTrack && (
<Source id="route" type="geojson" data={trackData.track}>
<Layer
id="route"
type="line"
paint={{
'line-width': ['interpolate', ['linear'], ['zoom'], 14, 2, 17, 5],
'line-color': '#F06292',
}}
/>
<Layer id="route" {...trackLayer} />
</Source>
)}