maputnik/src/components/map/FeatureLayerPopup.jsx

132 lines
3.8 KiB
React
Raw Normal View History

2016-12-24 15:24:22 +01:00
import React from 'react'
2017-11-08 09:47:36 +01:00
import PropTypes from 'prop-types'
2016-12-25 17:46:18 +01:00
import LayerIcon from '../icons/LayerIcon'
import {latest, expression, function as styleFunction} from '@mapbox/mapbox-gl-style-spec'
2016-12-24 17:24:24 +01:00
2016-12-25 17:46:18 +01:00
function groupFeaturesBySourceLayer(features) {
const sources = {}
let returnedFeatures = {};
2016-12-25 17:46:18 +01:00
features.forEach(feature => {
if(returnedFeatures.hasOwnProperty(feature.layer.id)) {
returnedFeatures[feature.layer.id]++
const featureObject = sources[feature.layer['source-layer']].find(f => f.layer.id === feature.layer.id)
featureObject.counter = returnedFeatures[feature.layer.id]
} else {
sources[feature.layer['source-layer']] = sources[feature.layer['source-layer']] || []
sources[feature.layer['source-layer']].push(feature)
returnedFeatures[feature.layer.id] = 1
}
2016-12-25 17:46:18 +01:00
})
2016-12-25 17:46:18 +01:00
return sources
}
2016-12-24 17:24:24 +01:00
2017-01-09 23:04:08 +01:00
class FeatureLayerPopup extends React.Component {
2017-11-08 09:47:36 +01:00
static propTypes = {
2018-01-08 22:18:30 +01:00
onLayerSelect: PropTypes.func.isRequired,
2018-10-27 15:08:23 +02:00
features: PropTypes.array,
zoom: PropTypes.number,
2017-11-08 09:47:36 +01:00
}
_getFeatureColor(feature, zoom) {
try {
const paintProps = feature.layer.paint;
let propName;
if(paintProps.hasOwnProperty("text-color") && paintProps["text-color"]) {
propName = "text-color";
}
else if (paintProps.hasOwnProperty("fill-color") && paintProps["fill-color"]) {
propName = "fill-color";
}
else if (paintProps.hasOwnProperty("line-color") && paintProps["line-color"]) {
propName = "line-color";
}
else if (paintProps.hasOwnProperty("fill-extrusion-color") && paintProps["fill-extrusion-color"]) {
propName = "fill-extrusion-color";
}
if(propName) {
const propertySpec = latest["paint_"+feature.layer.type][propName];
let color = feature.layer.paint[propName];
if(typeof(color) === "object") {
if(color.stops) {
color = styleFunction.convertFunction(color, propertySpec);
}
2016-12-25 17:46:18 +01:00
const exprResult = expression.createExpression(color, propertySpec);
const val = exprResult.value.evaluate({
zoom: zoom
}, feature);
return val.toString();
}
else {
return color;
}
}
else {
// Default color
return "black";
}
}
// This is quite complex, just incase there's an edgecase we're missing
// always return black if we get an unexpected error.
catch (err) {
console.error("Unable to get feature color, error:", err);
return "black";
}
}
render() {
const sources = groupFeaturesBySourceLayer(this.props.features)
const items = Object.keys(sources).map(vectorLayerId => {
const layers = sources[vectorLayerId].map((feature, idx) => {
const featureColor = this._getFeatureColor(feature, this.props.zoom);
return <div
key={idx}
className="maputnik-popup-layer"
2017-01-11 11:35:33 +01:00
>
<div
className="maputnik-popup-layer__swatch"
style={{background: featureColor}}
></div>
<label
className="maputnik-popup-layer__label"
onClick={() => {
this.props.onLayerSelect(feature.layer.id)
}}
>
<LayerIcon type={feature.layer.type} style={{
width: 14,
height: 14,
paddingRight: 3
}}/>
{feature.layer.id}
{feature.counter && <span> × {feature.counter}</span>}
</label>
</div>
2016-12-25 17:46:18 +01:00
})
2017-01-10 09:38:27 +01:00
return <div key={vectorLayerId}>
2017-01-11 11:35:33 +01:00
<div className="maputnik-popup-layer-id">{vectorLayerId}</div>
2016-12-25 17:46:18 +01:00
{layers}
</div>
})
2017-01-11 11:35:33 +01:00
return <div className="maputnik-feature-layer-popup">
2016-12-25 17:46:18 +01:00
{items}
2016-12-24 17:24:24 +01:00
</div>
2016-12-24 15:24:22 +01:00
}
}
2017-01-09 23:04:08 +01:00
export default FeatureLayerPopup