add MapShapes, analog of MapSites

This commit is contained in:
Lachlan Kermode
2019-01-18 10:41:06 +00:00
parent 6226dc3e85
commit fb46948b77
6 changed files with 89 additions and 41 deletions

View File

@@ -10,6 +10,7 @@ import 'leaflet';
import { isNotNullNorUndefined } from '../js/utilities';
import MapSites from './MapSites.jsx';
import MapShapes from './MapShapes.jsx';
import MapEvents from './MapEvents.jsx';
import MapSelectedEvents from './MapSelectedEvents.jsx';
import MapNarratives from './MapNarratives.jsx';
@@ -147,6 +148,17 @@ class Map extends React.Component {
);
}
renderShapes() {
return (
<MapShapes
shapes={this.props.domain.shapes}
map={this.map}
mapTransformX={this.state.mapTransformX}
mapTransformY={this.state.mapTransformY}
/>
)
}
renderNarratives() {
return (
<MapNarratives
@@ -223,16 +235,22 @@ class Map extends React.Component {
render() {
const { isShowingSites } = this.props.app.flags
const classes = this.props.app.narrative ? 'map-wrapper narrative-mode' : 'map-wrapper';
const innerMap = !!this.map ? (
<React.Fragment>
{this.renderTiles()}
{this.renderMarkers()}
{isShowingSites ? this.renderSites() : null}
{this.renderShapes()}
{this.renderEvents()}
{this.renderNarratives()}
{this.renderSelected()}
</React.Fragment>
) : null
return (
<div className={classes}>
<div id={this.props.ui.dom.map} />
{(this.map !== null) ? this.renderTiles() : ''}
{(this.map !== null) ? this.renderMarkers() : ''}
{(this.map !== null) && isShowingSites ? this.renderSites() : ''}
{(this.map !== null) ? this.renderEvents() : ''}
{(this.map !== null) ? this.renderNarratives() : ''}
{(this.map !== null) ? this.renderSelected() : ''}
{innerMap}
</div>
);
}
@@ -244,7 +262,8 @@ function mapStateToProps(state) {
locations: selectors.selectLocations(state),
narratives: selectors.selectNarratives(state),
categories: selectors.selectCategories(state),
sites: selectors.getSites(state)
sites: selectors.getSites(state),
shapes: selectors.getShapes(state)
},
app: {
views: state.app.filters.views,

View File

@@ -0,0 +1,33 @@
import React from 'react';
function MapShapes({ map, shapes, mapTransformX, mapTransformY }) {
function projectPoint(location) {
const latLng = new L.LatLng(location[0], location[1]);
return {
x: map.latLngToLayerPoint(latLng).x + mapTransformX,
y: map.latLngToLayerPoint(latLng).y + mapTransformY
};
}
function renderShape(shape) {
const coords = shape.points.map(projectPoint)
return coords.map(pt => (
<div
className="leaflet-tooltip shape-label leaflet-zoom-animated leaflet-tooltip-top"
style={{ opacity: 1, transform: `translate3d(calc(${pt.x}px - 50%), ${pt.y - 25}px, 0px)`}}>
{shape.name}
</div>
));
}
if (!shapes || !shapes.length) return null;
return (
<div className="shapes-layer">
{shapes.map(renderShape)}
</div>
)
}
export default MapShapes;

View File

@@ -1,36 +1,33 @@
import React from 'react';
class MapSites extends React.Component {
projectPoint(location) {
function MapSites({ map, sites, mapTransformX, mapTransformY }) {
function projectPoint(location) {
const latLng = new L.LatLng(location[0], location[1]);
return {
x: this.props.map.latLngToLayerPoint(latLng).x + this.props.mapTransformX,
y: this.props.map.latLngToLayerPoint(latLng).y + this.props.mapTransformY
x: map.latLngToLayerPoint(latLng).x + mapTransformX,
y: map.latLngToLayerPoint(latLng).y + mapTransformY
};
}
renderSite(site) {
const { x, y } = this.projectPoint([site.latitude, site.longitude]);
function renderSite(site) {
const { x, y } = projectPoint([site.latitude, site.longitude]);
return (<div
className="leaflet-tooltip site-label leaflet-zoom-animated leaflet-tooltip-top"
style={{ opacity: 1, transform: `translate3d(calc(${x}px - 50%), ${y - 25}px, 0px)`}}>
{site.site}
</div>
className="leaflet-tooltip site-label leaflet-zoom-animated leaflet-tooltip-top"
style={{ opacity: 1, transform: `translate3d(calc(${x}px - 50%), ${y - 25}px, 0px)`}}>
{site.site}
</div>
);
}
render () {
if (!this.props.sites || !this.props.sites.length) return <div />;
if (!sites || !sites.length) return null;
return (
<div className="sites-layer">
{this.props.sites.map(site => { return this.renderSite(site); })}
</div>
)
}
return (
<div className="sites-layer">
{sites.map(renderSite)}
</div>
)
}
export default MapSites;
export default MapSites;

View File

@@ -119,19 +119,14 @@ export function validateDomain (domain) {
validateObject(domain.sources, 'sources', sourceSchema)
validateObject(domain.shapes, 'shapes', shapeSchema)
sanitizedDomain.shapes = sanitizedDomain.shapes.map(shape => {
const points = shape.items.map(coords => {
const _coords = coords.replace(/\s/g, '').split(',')
return {
lat: parseFloat(_coords[0]),
lon: parseFloat(_coords[1])
}
})
return {
// NB: [lat, lon] array is best format for projecting into map
sanitizedDomain.shapes = sanitizedDomain.shapes.map(shape => ({
name: shape.name,
points
}
})
points: shape.items.map(coords => (
coords.replace(/\s/g, '').split(',')
))
})
)
// Message the number of failed items in domain
Object.keys(discardedDomain).forEach(disc => {

View File

@@ -65,14 +65,14 @@
}
}
.sites-layer {
.sites-layer, .shapes-layer {
position: fixed;
top: 0px;
left: 110px;
}
&.narrative-mode {
.sites-layer {
.sites-layer, .shapes-layer {
position: fixed;
top: 0px;
left: 0px;

View File

@@ -15,6 +15,10 @@ export const getSites = (state) => {
}
export const getSources = state => {
if (process.env.features.USE_SOURCES) return state.domain.sources
return {}
}
export const getShapes = state => {
if (process.env.features.USE_SHAPES) return state.domain.shapes
return []
}
export const getNotifications = state => state.domain.notifications