mirror of
https://github.com/maputnik/editor.git
synced 2026-08-26 15:07:41 +00:00
Another one bites the dust
This commit is contained in:
@@ -1,15 +1,15 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import MapLibreGl from 'maplibre-gl'
|
import MapLibreGl, {LayerSpecification, Map, MapOptions, SourceSpecification, StyleSpecification} from 'maplibre-gl'
|
||||||
|
// @ts-ignore
|
||||||
import MapboxInspect from 'mapbox-gl-inspect'
|
import MapboxInspect from 'mapbox-gl-inspect'
|
||||||
import MapMaplibreGlLayerPopup from './MapMaplibreGlLayerPopup'
|
// @ts-ignore
|
||||||
import MapMaplibreGlFeaturePropertyPopup from './MapMaplibreGlFeaturePropertyPopup'
|
|
||||||
import tokens from '../config/tokens.json'
|
|
||||||
import colors from 'mapbox-gl-inspect/lib/colors'
|
import colors from 'mapbox-gl-inspect/lib/colors'
|
||||||
|
import MapMaplibreGlLayerPopup from './MapMaplibreGlLayerPopup'
|
||||||
|
import MapMaplibreGlFeaturePropertyPopup, { InspectFeature } from './MapMaplibreGlFeaturePropertyPopup'
|
||||||
import Color from 'color'
|
import Color from 'color'
|
||||||
import ZoomControl from '../libs/zoomcontrol'
|
import ZoomControl from '../libs/zoomcontrol'
|
||||||
import { colorHighlightedLayer } from '../libs/highlight'
|
import { HighlightedLayer, colorHighlightedLayer } from '../libs/highlight'
|
||||||
import 'maplibre-gl/dist/maplibre-gl.css'
|
import 'maplibre-gl/dist/maplibre-gl.css'
|
||||||
import '../maplibregl.css'
|
import '../maplibregl.css'
|
||||||
import '../libs/maplibre-rtl'
|
import '../libs/maplibre-rtl'
|
||||||
@@ -17,26 +17,26 @@ import '../libs/maplibre-rtl'
|
|||||||
|
|
||||||
const IS_SUPPORTED = MapLibreGl.supported();
|
const IS_SUPPORTED = MapLibreGl.supported();
|
||||||
|
|
||||||
function renderPopup(popup, mountNode) {
|
function renderPopup(popup: JSX.Element, mountNode: ReactDOM.Container) {
|
||||||
ReactDOM.render(popup, mountNode);
|
ReactDOM.render(popup, mountNode);
|
||||||
return mountNode;
|
return mountNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildInspectStyle(originalMapStyle, coloredLayers, highlightedLayer) {
|
function buildInspectStyle(originalMapStyle: StyleSpecification, coloredLayers: HighlightedLayer[], highlightedLayer?: HighlightedLayer) {
|
||||||
const backgroundLayer = {
|
const backgroundLayer = {
|
||||||
"id": "background",
|
"id": "background",
|
||||||
"type": "background",
|
"type": "background",
|
||||||
"paint": {
|
"paint": {
|
||||||
"background-color": '#1c1f24',
|
"background-color": '#1c1f24',
|
||||||
}
|
}
|
||||||
}
|
} as LayerSpecification
|
||||||
|
|
||||||
const layer = colorHighlightedLayer(highlightedLayer)
|
const layer = colorHighlightedLayer(highlightedLayer)
|
||||||
if(layer) {
|
if(layer) {
|
||||||
coloredLayers.push(layer)
|
coloredLayers.push(layer)
|
||||||
}
|
}
|
||||||
|
|
||||||
const sources = {}
|
const sources: {[key:string]: SourceSpecification} = {}
|
||||||
Object.keys(originalMapStyle.sources).forEach(sourceId => {
|
Object.keys(originalMapStyle.sources).forEach(sourceId => {
|
||||||
const source = originalMapStyle.sources[sourceId]
|
const source = originalMapStyle.sources[sourceId]
|
||||||
if(source.type !== 'raster' && source.type !== 'raster-dem') {
|
if(source.type !== 'raster' && source.type !== 'raster-dem') {
|
||||||
@@ -47,32 +47,43 @@ function buildInspectStyle(originalMapStyle, coloredLayers, highlightedLayer) {
|
|||||||
const inspectStyle = {
|
const inspectStyle = {
|
||||||
...originalMapStyle,
|
...originalMapStyle,
|
||||||
sources: sources,
|
sources: sources,
|
||||||
layers: [backgroundLayer].concat(coloredLayers)
|
layers: [backgroundLayer].concat(coloredLayers as LayerSpecification[])
|
||||||
}
|
}
|
||||||
return inspectStyle
|
return inspectStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class MapMaplibreGl extends React.Component {
|
type MapMaplibreGlProps = {
|
||||||
static propTypes = {
|
onDataChange?(...args: unknown[]): unknown
|
||||||
onDataChange: PropTypes.func,
|
onLayerSelect(...args: unknown[]): unknown
|
||||||
onLayerSelect: PropTypes.func.isRequired,
|
mapStyle: StyleSpecification
|
||||||
mapStyle: PropTypes.object.isRequired,
|
inspectModeEnabled: boolean
|
||||||
inspectModeEnabled: PropTypes.bool.isRequired,
|
highlightedLayer?: HighlightedLayer
|
||||||
highlightedLayer: PropTypes.object,
|
options?: MapOptions & {
|
||||||
options: PropTypes.object,
|
showTileBoundaries?: boolean
|
||||||
replaceAccessTokens: PropTypes.func.isRequired,
|
showCollisionBoxes?: boolean
|
||||||
onChange: PropTypes.func.isRequired,
|
showOverdrawInspector?: boolean
|
||||||
}
|
}
|
||||||
|
replaceAccessTokens(mapStyle: StyleSpecification): StyleSpecification
|
||||||
|
onChange(...args: unknown[]): unknown
|
||||||
|
};
|
||||||
|
|
||||||
|
type MapMaplibreGlState = {
|
||||||
|
map: Map | null
|
||||||
|
inspect: MapboxInspect | null
|
||||||
|
zoom?: number
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class MapMaplibreGl extends React.Component<MapMaplibreGlProps, MapMaplibreGlState> {
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
onMapLoaded: () => {},
|
onMapLoaded: () => {},
|
||||||
onDataChange: () => {},
|
onDataChange: () => {},
|
||||||
onLayerSelect: () => {},
|
onLayerSelect: () => {},
|
||||||
onChange: () => {},
|
onChange: () => {},
|
||||||
options: {},
|
options: {} as MapOptions,
|
||||||
}
|
}
|
||||||
|
container: HTMLDivElement | null = null
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props: MapMaplibreGlProps) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
map: null,
|
map: null,
|
||||||
@@ -80,7 +91,7 @@ export default class MapMaplibreGl extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMapFromProps(props) {
|
updateMapFromProps(props: MapMaplibreGlProps) {
|
||||||
if(!IS_SUPPORTED) return;
|
if(!IS_SUPPORTED) return;
|
||||||
|
|
||||||
if(!this.state.map) return
|
if(!this.state.map) return
|
||||||
@@ -93,7 +104,7 @@ export default class MapMaplibreGl extends React.Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps: MapMaplibreGlProps, nextState: MapMaplibreGlState) {
|
||||||
let should = false;
|
let should = false;
|
||||||
try {
|
try {
|
||||||
should = JSON.stringify(this.props) !== JSON.stringify(nextProps) || JSON.stringify(this.state) !== JSON.stringify(nextState);
|
should = JSON.stringify(this.props) !== JSON.stringify(nextProps) || JSON.stringify(this.state) !== JSON.stringify(nextState);
|
||||||
@@ -103,7 +114,7 @@ export default class MapMaplibreGl extends React.Component {
|
|||||||
return should;
|
return should;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
componentDidUpdate() {
|
||||||
if(!IS_SUPPORTED) return;
|
if(!IS_SUPPORTED) return;
|
||||||
|
|
||||||
const map = this.state.map;
|
const map = this.state.map;
|
||||||
@@ -128,9 +139,9 @@ export default class MapMaplibreGl extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
map.showTileBoundaries = this.props.options.showTileBoundaries;
|
map.showTileBoundaries = this.props.options?.showTileBoundaries!;
|
||||||
map.showCollisionBoxes = this.props.options.showCollisionBoxes;
|
map.showCollisionBoxes = this.props.options?.showCollisionBoxes!;
|
||||||
map.showOverdrawInspector = this.props.options.showOverdrawInspector;
|
map.showOverdrawInspector = this.props.options?.showOverdrawInspector!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +150,7 @@ export default class MapMaplibreGl extends React.Component {
|
|||||||
|
|
||||||
const mapOpts = {
|
const mapOpts = {
|
||||||
...this.props.options,
|
...this.props.options,
|
||||||
container: this.container,
|
container: this.container!,
|
||||||
style: this.props.mapStyle,
|
style: this.props.mapStyle,
|
||||||
hash: true,
|
hash: true,
|
||||||
maxZoom: 24
|
maxZoom: 24
|
||||||
@@ -154,9 +165,9 @@ export default class MapMaplibreGl extends React.Component {
|
|||||||
}
|
}
|
||||||
mapViewChange();
|
mapViewChange();
|
||||||
|
|
||||||
map.showTileBoundaries = mapOpts.showTileBoundaries;
|
map.showTileBoundaries = mapOpts.showTileBoundaries!;
|
||||||
map.showCollisionBoxes = mapOpts.showCollisionBoxes;
|
map.showCollisionBoxes = mapOpts.showCollisionBoxes!;
|
||||||
map.showOverdrawInspector = mapOpts.showOverdrawInspector;
|
map.showOverdrawInspector = mapOpts.showOverdrawInspector!;
|
||||||
|
|
||||||
const zoomControl = new ZoomControl;
|
const zoomControl = new ZoomControl;
|
||||||
map.addControl(zoomControl, 'top-right');
|
map.addControl(zoomControl, 'top-right');
|
||||||
@@ -175,11 +186,11 @@ export default class MapMaplibreGl extends React.Component {
|
|||||||
showInspectMapPopupOnHover: true,
|
showInspectMapPopupOnHover: true,
|
||||||
showInspectButton: false,
|
showInspectButton: false,
|
||||||
blockHoverPopupOnClick: true,
|
blockHoverPopupOnClick: true,
|
||||||
assignLayerColor: (layerId, alpha) => {
|
assignLayerColor: (layerId: string, alpha: number) => {
|
||||||
return Color(colors.brightColor(layerId, alpha)).desaturate(0.5).string()
|
return Color(colors.brightColor(layerId, alpha)).desaturate(0.5).string()
|
||||||
},
|
},
|
||||||
buildInspectStyle: (originalMapStyle, coloredLayers) => buildInspectStyle(originalMapStyle, coloredLayers, this.props.highlightedLayer),
|
buildInspectStyle: (originalMapStyle: StyleSpecification, coloredLayers: HighlightedLayer[]) => buildInspectStyle(originalMapStyle, coloredLayers, this.props.highlightedLayer),
|
||||||
renderPopup: features => {
|
renderPopup: (features: InspectFeature[]) => {
|
||||||
if(this.props.inspectModeEnabled) {
|
if(this.props.inspectModeEnabled) {
|
||||||
return renderPopup(<MapMaplibreGlFeaturePropertyPopup features={features} />, tmpNode);
|
return renderPopup(<MapMaplibreGlFeaturePropertyPopup features={features} />, tmpNode);
|
||||||
} else {
|
} else {
|
||||||
@@ -199,7 +210,7 @@ export default class MapMaplibreGl extends React.Component {
|
|||||||
|
|
||||||
map.on("data", e => {
|
map.on("data", e => {
|
||||||
if(e.dataType !== 'tile') return
|
if(e.dataType !== 'tile') return
|
||||||
this.props.onDataChange({
|
this.props.onDataChange!({
|
||||||
map: this.state.map
|
map: this.state.map
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -208,7 +219,7 @@ export default class MapMaplibreGl extends React.Component {
|
|||||||
console.log("ERROR", e);
|
console.log("ERROR", e);
|
||||||
})
|
})
|
||||||
|
|
||||||
map.on("zoom", e => {
|
map.on("zoom", _e => {
|
||||||
this.setState({
|
this.setState({
|
||||||
zoom: map.getZoom()
|
zoom: map.getZoom()
|
||||||
});
|
});
|
||||||
@@ -218,7 +229,7 @@ export default class MapMaplibreGl extends React.Component {
|
|||||||
map.on("zoomend", mapViewChange);
|
map.on("zoomend", mapViewChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
onLayerSelectById = (id) => {
|
onLayerSelectById = (id: string) => {
|
||||||
const index = this.props.mapStyle.layers.findIndex(layer => layer.id === id);
|
const index = this.props.mapStyle.layers.findIndex(layer => layer.id === id);
|
||||||
this.props.onLayerSelect(index);
|
this.props.onLayerSelect(index);
|
||||||
}
|
}
|
||||||
+21
-19
@@ -4,38 +4,40 @@ import stylegen from 'mapbox-gl-inspect/lib/stylegen'
|
|||||||
import colors from 'mapbox-gl-inspect/lib/colors'
|
import colors from 'mapbox-gl-inspect/lib/colors'
|
||||||
import {FilterSpecification,LayerSpecification } from '@maplibre/maplibre-gl-style-spec'
|
import {FilterSpecification,LayerSpecification } from '@maplibre/maplibre-gl-style-spec'
|
||||||
|
|
||||||
export function colorHighlightedLayer(layer: LayerSpecification) {
|
export type HighlightedLayer = LayerSpecification & {filter?: FilterSpecification};
|
||||||
if(!layer || layer.type === 'background' || layer.type === 'raster') return null
|
|
||||||
|
|
||||||
function changeLayer(l: LayerSpecification & {filter?: FilterSpecification}) {
|
function changeLayer(l: HighlightedLayer, layer: LayerSpecification) {
|
||||||
if(l.type === 'circle') {
|
if(l.type === 'circle') {
|
||||||
l.paint!['circle-radius'] = 3
|
l.paint!['circle-radius'] = 3
|
||||||
} else if(l.type === 'line') {
|
} else if(l.type === 'line') {
|
||||||
l.paint!['line-width'] = 2
|
l.paint!['line-width'] = 2
|
||||||
}
|
|
||||||
|
|
||||||
if("filter" in layer) {
|
|
||||||
l.filter = layer.filter
|
|
||||||
} else {
|
|
||||||
delete l['filter']
|
|
||||||
}
|
|
||||||
l.id = l.id + '_highlight'
|
|
||||||
return l
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if("filter" in layer) {
|
||||||
|
l.filter = layer.filter
|
||||||
|
} else {
|
||||||
|
delete l['filter']
|
||||||
|
}
|
||||||
|
l.id = l.id + '_highlight'
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
export function colorHighlightedLayer(layer?: LayerSpecification): HighlightedLayer | null {
|
||||||
|
if(!layer || layer.type === 'background' || layer.type === 'raster') return null
|
||||||
|
|
||||||
const sourceLayerId = layer['source-layer'] || ''
|
const sourceLayerId = layer['source-layer'] || ''
|
||||||
const color = colors.brightColor(sourceLayerId, 1);
|
const color = colors.brightColor(sourceLayerId, 1);
|
||||||
|
|
||||||
if(layer.type === "fill" || layer.type === 'fill-extrusion') {
|
if(layer.type === "fill" || layer.type === 'fill-extrusion') {
|
||||||
return changeLayer(stylegen.polygonLayer(color, color, layer.source, layer['source-layer']))
|
return changeLayer(stylegen.polygonLayer(color, color, layer.source, layer['source-layer']), layer)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(layer.type === "symbol" || layer.type === 'circle') {
|
if(layer.type === "symbol" || layer.type === 'circle') {
|
||||||
return changeLayer(stylegen.circleLayer(color, layer.source, layer['source-layer']))
|
return changeLayer(stylegen.circleLayer(color, layer.source, layer['source-layer']), layer)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(layer.type === 'line') {
|
if(layer.type === 'line') {
|
||||||
return changeLayer(stylegen.lineLayer(color, layer.source, layer['source-layer']))
|
return changeLayer(stylegen.lineLayer(color, layer.source, layer['source-layer']), layer)
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
|
|||||||
Reference in New Issue
Block a user