Skip to content

Commit e24586c

Browse files
committed
Add support for Google Map Tiles layers #207
2 parents 5b183f7 + 1640235 commit e24586c

File tree

5 files changed

+151
-0
lines changed

5 files changed

+151
-0
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
### Added
10+
11+
- Add support for Google Map Tiles layers. #207
12+
913
### Changed
1014

1115
- Update open layers to version 10.4.0. #206

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,22 @@ const wmsOpts = {
185185
};
186186
const wmsLayer = myMap.addLayer('wms', wmsOpts);
187187

188+
// Adding a Google Map Tiles layer. This requires registering a Google Developer
189+
// account and creating your own Map Tiles API key. See the following
190+
// documentation on creating and restricting API keys.
191+
// "Google strongly recommends that you restrict your API keys by limiting their
192+
// usage to those only APIs needed for your application. Restricting API keys
193+
// adds security to your application by protecting it from unwarranted requests."
194+
// https://developers.google.com/maps/documentation/tile/get-api-key
195+
const googleMapOpts = {
196+
title: 'Google Satellite',
197+
key: 'AIzaSyBEB1xUvz8LG_XexTVKv5ghXEPaCzF9eng', // replace with your API key.
198+
mapType: 'satellite',
199+
visible: true, // defaults to true
200+
base: true, // defaults to false
201+
}
202+
const googleMapLayer = myMap.addLayer('google', googleMapOpts);
203+
188204
// Adding a ArcGIS MapServer tile layer.
189205
const arcGISTileOpts = {
190206
title: 'StateCityHighway_USA', // defaults to 'arcgis-tile'
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.ol-google-logo-attrib.ol-control {
2+
/* By default position the logo above the scale line and to the right of the snapping grid controls. */
3+
bottom: 2.75em;
4+
left: 3.5em;
5+
6+
/* Remove the normal grey control background */
7+
background-color: rgba(255, 255, 255, 0);
8+
}
9+
10+
@media (max-width: 767px) {
11+
.map-with-ol-side-panel .ol-google-logo-attrib.ol-control:not(.ol-side-panel) {
12+
/* If the side-panel is expanded on small screens, don't let it get pushed out of view. */
13+
margin-left: 0;
14+
15+
/* Add a short transition so it doesn't jump so much. */
16+
transition: margin-left 500ms;
17+
}
18+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import Control from 'ol/control/Control';
2+
import Google from 'ol/source/Google';
3+
import { CLASS_CONTROL, CLASS_UNSELECTABLE } from 'ol/css';
4+
5+
import './GoogleLogoAttribution.css';
6+
7+
/**
8+
* @classdesc
9+
* OpenLayers GoogleLogoAttribution Control.
10+
*
11+
* @api
12+
*/
13+
class GoogleLogoAttribution extends Control {
14+
15+
/**
16+
* @param {Options=} opts GoogleLogoAttribution options.
17+
*/
18+
constructor(opts) {
19+
const options = opts || {};
20+
21+
// Call the parent control constructor.
22+
super({
23+
element: document.createElement('div'),
24+
target: options.target,
25+
});
26+
27+
// Define the class name.
28+
const className = 'ol-google-logo-attrib';
29+
30+
// Add the CSS classes to the control element.
31+
const { element } = this;
32+
element.className = `${className} ${CLASS_UNSELECTABLE} ${CLASS_CONTROL}`;
33+
34+
const logoImg = document.createElement('img');
35+
logoImg.style.pointerEvents = 'none';
36+
logoImg.src = 'https://developers.google.com/static/maps/documentation/images/google_on_white.png';
37+
38+
element.appendChild(logoImg);
39+
}
40+
41+
/**
42+
* @inheritDoc
43+
* @api
44+
*/
45+
setMap(map) {
46+
const oldMap = this.getMap();
47+
if (map === oldMap) {
48+
return;
49+
}
50+
if (oldMap) {
51+
52+
// Cleanup the old event listener
53+
if (this.onMapChangeLayerGroups) {
54+
oldMap.getLayerGroup().un('change', this.onMapChangeLayerGroups.listener);
55+
this.onMapChangeLayerGroups = null;
56+
}
57+
}
58+
super.setMap(map);
59+
60+
if (map) {
61+
62+
// Toggle the control visibility upon any top-level layer group change
63+
const updateState = () => {
64+
const anyVisibleGoogleLayers = map.getAllLayers().some(layer => layer.isVisible() && typeof layer.getSource === 'function' && layer.getSource() instanceof Google);
65+
66+
this.element.style.display = anyVisibleGoogleLayers ? 'block' : 'none';
67+
};
68+
69+
this.onMapChangeLayerGroups = map.getLayerGroup().on('change', updateState);
70+
updateState();
71+
}
72+
}
73+
74+
}
75+
76+
export default GoogleLogoAttribution;

src/instance/methods/layer.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Import source types, layer types, and formats.
22
import VectorSource from 'ol/source/Vector';
33
import Cluster from 'ol/source/Cluster';
4+
import Google from 'ol/source/Google';
45
import TileArcGISRest from 'ol/source/TileArcGISRest';
56
import TileWMS from 'ol/source/TileWMS';
67
import XYZ from 'ol/source/XYZ';
@@ -19,6 +20,9 @@ import colorStyles, { clusterStyle } from '../../styles';
1920
// Import readFeatures function.
2021
import readFeatures from './features';
2122

23+
// Import GoogleLogoAttribution control.
24+
import GoogleLogoAttribution from '../../control/Google/GoogleLogoAttribution';
25+
2226
// Set withCredentials to true for all XHR requests made via OpenLayers'
2327
// feature loader. Typically farmOS requires authentication in order to
2428
// retrieve data from its GeoJSON endpoints. Setting withCredentials to true
@@ -103,6 +107,29 @@ function addGeoJSONLayer({
103107
return layer;
104108
}
105109

110+
// Add a Google Map Tiles layer to the map.
111+
function addGoogleMapTilesLayer({
112+
title = 'google-map-tiles', key, mapType = 'satellite', layerTypes = [], language = 'en-US', region = 'US', apiOptions = null, visible = true, base = true,
113+
}) {
114+
const source = new Google({
115+
key,
116+
mapType,
117+
layerTypes,
118+
language,
119+
region,
120+
apiOptions,
121+
scale: 'scaleFactor2x',
122+
highDpi: true,
123+
});
124+
const layer = new TileLayer({
125+
title,
126+
source,
127+
visible,
128+
type: base ? 'base' : 'normal',
129+
});
130+
return layer;
131+
}
132+
106133
// Add a Tile ArcGIS MapServer layer to the map.
107134
function addTileArcGISMapServerLayer({
108135
title = 'arcgis-tile', url, params, visible = true, base = false, attribution = '', crossOrigin = null,
@@ -226,6 +253,16 @@ export default function addLayer(type, opts = {}) {
226253
}
227254
layer = addGeoJSONLayer(opts);
228255
}
256+
if (type.toLowerCase() === 'google') {
257+
if (!opts.key) {
258+
throw new Error('Missing a Google Map Tiles API key.');
259+
}
260+
layer = addGoogleMapTilesLayer(opts);
261+
if (!this.map.getControls().getArray()
262+
.some(control => control instanceof GoogleLogoAttribution)) {
263+
this.map.addControl(new GoogleLogoAttribution());
264+
}
265+
}
229266
if (type.toLowerCase() === 'arcgis-tile') {
230267
if (!opts.url) {
231268
throw new Error('Missing a ArcGIS MapServer url.');

0 commit comments

Comments
 (0)