colouring-montreal/app/src/frontend/map.js

136 lines
4.8 KiB
JavaScript
Raw Normal View History

2018-09-13 15:35:27 -04:00
import React, { Component, Fragment } from 'react';
import { Map, TileLayer, ZoomControl, AttributionControl } from 'react-leaflet-universal';
import queryString from 'query-string';
import '../../node_modules/leaflet/dist/leaflet.css'
import './map.css'
2018-09-13 11:03:49 -04:00
import ThemeSwitcher from './theme-switcher';
const OS_API_KEY = 'NVUxtY5r8eA6eIfwrPTAGKrAAsoeI9E9';
/**
* Map area
*/
class ColouringMap extends Component {
2018-09-10 07:40:25 -04:00
constructor(props) {
super(props);
this.state = {
2018-09-27 16:37:32 -04:00
theme: 'night',
2018-09-10 07:40:25 -04:00
lat: 51.5245255,
lng: -0.1338422,
2018-09-10 18:34:56 -04:00
zoom: 16
2018-09-10 07:40:25 -04:00
};
this.handleClick = this.handleClick.bind(this);
2018-09-13 11:03:49 -04:00
this.themeSwitch = this.themeSwitch.bind(this);
2018-09-10 07:40:25 -04:00
}
handleClick(e) {
if (this.props.match.url.match('edit')){
// don't navigate away from edit view
return
}
2018-09-10 07:40:25 -04:00
var lat = e.latlng.lat
var lng = e.latlng.lng
const is_building = /building/.test(this.props.match.url);
const new_cat = get_cat(is_building, this.props.location, this.props.match.url);
2018-09-10 07:40:25 -04:00
fetch(
2018-09-30 16:10:03 -04:00
'/buildings/locate?lat='+lat+'&lng='+lng
2018-09-10 07:40:25 -04:00
).then(
(res) => res.json()
).then(function(data){
2018-09-30 16:54:47 -04:00
if (data && data.length){
const building = data[0];
this.props.selectBuilding(building);
this.props.history.push(`/building/${building.building_id}.html?cat=${new_cat}`);
2018-09-10 07:40:25 -04:00
} else {
// deselect but keep/return to expected colour theme
this.props.selectBuilding(undefined);
const map_cat = new_cat || 'age';
this.props.history.push(`/map/${map_cat}.html`);
2018-09-10 07:40:25 -04:00
}
2018-09-10 18:34:56 -04:00
}.bind(this)).catch(
(err) => console.error(err)
)
}
2018-09-13 11:03:49 -04:00
themeSwitch(e) {
e.preventDefault();
const newTheme = (this.state.theme === 'light')? 'night' : 'light';
this.setState({theme: newTheme});
}
render() {
const position = [this.state.lat, this.state.lng];
2018-09-13 18:55:53 -04:00
// baselayer
const key = OS_API_KEY
const tilematrixSet = 'EPSG:3857'
2018-09-13 11:03:49 -04:00
const layer = (this.state.theme === 'light')? 'Light 3857' : 'Night 3857';
const url = `https://api2.ordnancesurvey.co.uk/mapping_api/v1/service/zxy/${tilematrixSet}/${layer}/{z}/{x}/{y}.png?key=${key}`
const attribution = 'Building attribute data is © Colouring London contributors. Maps contain OS data © Crown copyright: OS Maps baselayers and building outlines.'
2018-09-10 17:14:09 -04:00
2018-09-13 18:55:53 -04:00
// colour-data tiles
const is_building = /building/.test(this.props.match.url);
const cat = get_cat(is_building, this.props.location, this.props.match.url);
const tileset_by_cat = {
age: 'date_year',
size: 'size_storeys',
location: 'location',
like: 'likes',
}
const data_tileset = tileset_by_cat[cat];
const dataLayer = data_tileset?
<TileLayer key={data_tileset} url={`/tiles/${data_tileset}/{z}/{x}/{y}.png`} />
: null;
2018-09-10 18:34:56 -04:00
2018-09-13 18:55:53 -04:00
// highlight
2018-09-10 18:34:56 -04:00
const geometry_id = (this.props.building) ? this.props.building.geometry_id : undefined;
const highlight = `/tiles/highlight/{z}/{x}/{y}.png?highlight=${geometry_id}`
const highlightLayer = (is_building && this.props.building) ?
2018-09-30 16:54:47 -04:00
<TileLayer key={this.props.building.building_id} url={highlight} />
: null;
2018-09-10 17:14:09 -04:00
const base_layer_url = (this.state.theme === 'light')?
`/tiles/base_light/{z}/{x}/{y}.png`
: `/tiles/base_night/{z}/{x}/{y}.png`
return (
2018-09-13 15:35:27 -04:00
<Fragment>
<Map
center={position}
zoom={this.state.zoom}
minZoom={10}
maxZoom={18}
doubleClickZoom={false}
zoomControl={false}
attributionControl={false}
onClick={this.handleClick}
>
<TileLayer url={url} attribution={attribution} />
<TileLayer url={base_layer_url} />
2018-09-13 18:55:53 -04:00
{ dataLayer }
2018-09-13 15:35:27 -04:00
{ highlightLayer }
<ZoomControl position="topright" />
<AttributionControl prefix="" />
</Map>
2018-09-13 11:03:49 -04:00
<ThemeSwitcher onSubmit={this.themeSwitch} currentTheme={this.state.theme} />
2018-09-13 15:35:27 -04:00
</Fragment>
);
}
};
function get_cat(is_building, location, url) {
const search = (location && location.search)? queryString.parse(location.search) : {};
var cat, matches;
if (is_building) {
cat = search.cat;
} else {
matches = /\/map\/([^.]+).html/.exec(url);
cat = (matches && matches.length > 1)? matches[1] : "";
}
return cat;
}
export default ColouringMap;