make mapstyles simpler
This commit is contained in:
parent
15dfb2dc3b
commit
38b1b92210
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
|
|
|
@ -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>
|
||||
)}
|
||||
|
||||
|
|
Loading…
Reference in a new issue