Skip to content

Commit

Permalink
Updated to allow MultiMap to be altered dynamically after creation. S…
Browse files Browse the repository at this point in the history
…o new tile layers of maps can be added even if we don't initially know all of their details.
  • Loading branch information
DavidSouthgate committed Oct 13, 2020
1 parent 0299062 commit 1d40267
Show file tree
Hide file tree
Showing 12 changed files with 14,310 additions and 59 deletions.
13 changes: 13 additions & 0 deletions examples/react-dynamic/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# React Dynamic
This example shows React being used to display a dynamic map. A dynamic map being one which do not know all of the tile
layers and maps which need to be used when creating the MultiMap instance. Instead, we create a new MultiMap and add
the new tile layers and maps when they become available. Useful for preloading an initial layer whilst waiting for
another process to complete.

If you don't need to change tile layers or maps after creation see the [react example](../react/README.md).

## Usage
```
npm install
npm start
```
13,916 changes: 13,916 additions & 0 deletions examples/react-dynamic/package-lock.json

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions examples/react-dynamic/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.3",
"leaflet": "^1.7.1",
"proj4": "^2.6.2",
"proj4leaflet": "^1.0.2",
"@davidsouthgate/leaflet-multi-map": "../../"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
6 changes: 6 additions & 0 deletions examples/react-dynamic/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<!DOCTYPE html>
<html lang="en">
<body>
<div id="root"></div>
</body>
</html>
118 changes: 118 additions & 0 deletions examples/react-dynamic/src/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import React from "react";
import styles from "./App.module.css";

import L from "leaflet"
import "leaflet/dist/leaflet.css";
import "proj4leaflet";
import "@davidsouthgate/leaflet-multi-map";
import "@davidsouthgate/leaflet-multi-map/dist/leaflet-multi-map.css";

// Hack to get round marker not showing when using leaflet css from npm
// https://github.com/PaulLeCam/react-leaflet/issues/453#issuecomment-410450387
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
iconUrl: require('leaflet/dist/images/marker-icon.png'),
shadowUrl: require('leaflet/dist/images/marker-shadow.png')
});

export default class Test extends React.Component {
componentDidMount() {
const CENTER = [56.8, -3.4];
const API_KEY = "LgUCghKqtwvZEASSCReMCCD9vpJlhrL9";
const SERVICE_URL = "https://api.os.uk/maps/raster/v1/zxy";

let multiMap = L.multiMap("map", {
center: CENTER,
zoom: 7
});

multiMap.addTileLayer(
L.MultiMap.tileLayer("osOutdoor", {
title: "Ordnance Survey (Outdoor)",
vanillaTileLayer: L.tileLayer(SERVICE_URL + '/Outdoor_27700/{z}/{x}/{y}.png?key=' + API_KEY, {
attribution: "Contains OS data &copy; Crown copyright and database rights " + new Date().getFullYear()
})
})
);

multiMap.addMap(
L.MultiMap.map("map27700", {
tileLayerIds: [
"osOutdoor"
],
zoomOffset: 7,
vanillaOptions: {
crs: new L.Proj.CRS('EPSG:27700', '+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 +units=m +no_defs', {
resolutions: [ 896.0, 448.0, 224.0, 112.0, 56.0, 28.0, 14.0, 7.0, 3.5, 1.75 ],
origin: [ -238375.0, 1376256.0 ]
}),
}
})
);

setTimeout(function() {

multiMap.addTileLayer(
L.MultiMap.tileLayer("osLeisure", {
title: "Ordnance Survey (Leisure)",
vanillaTileLayer: L.tileLayer(SERVICE_URL + '/Leisure_27700/{z}/{x}/{y}.png?key=' + API_KEY, {
attribution: "Contains OS data &copy; Crown copyright and database rights " + new Date().getFullYear()
})
}), "map27700"
);

multiMap.addTileLayer(
L.MultiMap.tileLayer("openStreetMap", {
title: "OpenStreetMap",
vanillaTileLayer: L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: "&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors"
})
})
);

multiMap.addTileLayer(
L.MultiMap.tileLayer("openTopoMap", {
title: "OpenTopoMap",
vanillaTileLayer: L.tileLayer("https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png", {
attribution: "Map data: &copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors, <a href=\"http://viewfinderpanoramas.org\">SRTM</a> | Map style: &copy; <a href=\"https://opentopomap.org\">OpenTopoMap</a> (<a href=\"https://creativecommons.org/licenses/by-sa/3.0/\">CC-BY-SA</a>)"
})
})
);

multiMap.addMap(
L.MultiMap.map("map3857", {
tileLayerIds: [
"openStreetMap",
"openTopoMap"
],
zoomOffset: 0
})
);

console.log(multiMap.maps[0]);
}, 3000);

let cities = L.layerGroup(
[
L.marker([57.1498817, -2.1950666]).bindPopup("Aberdeen"),
L.marker([56.4745806, -3.0368723]).bindPopup("Dundee"),
L.marker([55.9544530, -3.1893327]).bindPopup("Edinburgh"),
L.marker([55.8554403, -4.3024976]).bindPopup("Glasgow"),
L.marker([57.4679914, -4.2568770]).bindPopup("Inverness"),
L.marker([56.3904758, -3.4842713]).bindPopup("Perth"),
L.marker([56.1168820, -3.9360940]).bindPopup("Stirling"),
]
);

multiMap.addOverlay("Cities", cities, {checked: true});
}

render() {
return (
<div>
<div id="map" className={styles.map}/>
</div>
)
}
}
5 changes: 5 additions & 0 deletions examples/react-dynamic/src/App.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.map {
width: 600px;
height: 600px;
background-color: red;
}
10 changes: 10 additions & 0 deletions examples/react-dynamic/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
7 changes: 7 additions & 0 deletions examples/react/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# React
This example shows React being used to display a static map. A static map being one which we know all of the tile layers
and maps needed when we create a MultiMap instance.

If you need to change tile layers or maps after creation see the [react-dynamic example](../react-dynamic/README.md).

## Usage
```
npm install
npm start
Expand Down
3 changes: 0 additions & 3 deletions examples/react/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 25 additions & 2 deletions src/map.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,37 @@
L.MultiMap.Map = L.Class.extend({
// Public Properties:
// id {string} The unique identifier for this map. Must be a unique DOM id.
// tileLayerIds [{string}] The IDs of the tile layers that should use this map
// zoomOffset {number} The difference in zoom for this map from the multimap zoom.
// vanillaOptions {object} Options which should be passed to the L.Map instance
// Private Properties:
// _overlayMaps {<Name> -> L.LayerGroup} Overlays which have been added to this map
// _tileLayerTitles [{string}] The names of the tile layers that should use this map
// _vanillaMap {L.Map} The vanilla leaflet map instance
// _vanillaLayersControl {L.Control.Layers} The layer controls used on this map
// _vanillaTileLayers {<Name> -> L.TileLayer} A map from a tile layer's name to the vanilla leaflet tile layer

initialize: function(id = null, options = {}) {
this.id = id ? id : null;
this.tileLayerIds = options.tileLayerIds ? options.tileLayerIds : [];
this.zoomOffset = options.zoomOffset ? options.zoomOffset : 0;
this.vanillaOptions = options.vanillaOptions ? options.vanillaOptions : {};
this._overlayMaps = {};
this._tileLayerTitles = [];
this._vanillaMap = null;
this._vanillaTileLayers = null;
this._vanillaLayersControl = null;
}
this._vanillaTileLayers = {};
},

_hasAnyLayer() {
let flag = false
for(const vanillaTileLayer of Object.values(this._vanillaTileLayers)) {
if(this._vanillaMap.hasLayer(vanillaTileLayer)) {
flag = true;
}
}
return flag;
},
});

L.MultiMap.map = function (id = null, options = {}) {
Expand Down
Loading

0 comments on commit 1d40267

Please sign in to comment.