Replacing your Google map with an OpenLayers Map

Since June 11, 2018, in order to use the google maps API, you must enable billing with a credit card and have a valid API key. Most sites will never exceed the free usage so having to register a credit card seems a bit pointless, especially for the likes of charities that may not even posses a credit card.

If you do not enable billing you will see something like -

This page can't load Google Maps correctly.

Existing Google Map

The code below plots a number of markers on the map and displays a popup with more information when the user clicks on one of the markers.


<script>
      function initialize() {

		var locations = [
	      	["Statue Of Liberty", 40.6892534, -74.0446426, "the-statue-of-libety", "photo-r49243.jpg", 1],
	      	["Central Park", 40.7828687, -73.9659076, "central-park", "photo-3122121.jpg", 2],
	      	["Rockefeller Center", 40.7562179,-73.9848441, "rockerfeller-center","photo-233444.jpg", 3]
	      	];

		var map = new google.maps.Map(document.getElementById('map-canvas'), {
		      zoom: 6,
			  scrollwheel: false,
		      center: new google.maps.LatLng(53.7633964,-4.8943857),
		      mapTypeId: google.maps.MapTypeId.ROADMAP
		    });

	    var infowindow = new google.maps.InfoWindow();

	    var marker, i;

	    for (i = 0; i < locations.length; i++) {  
	      marker = new google.maps.Marker({
	        position: new google.maps.LatLng(locations[i][1], locations[i][2]),
	        map: map
	      });

	      google.maps.event.addListener(marker, 'click', (function(marker, i) {
	        return function() {
	          infowindow.setContent('<a style="color:black; font-weight:600" href="http://www.somedomain.com/' + locations[i][3] + '">' + 
	          	'<img src="' +  locations[i][4] + '" width="200" />' + 
	          	'<div style="width:220px; margin-top:3px">' + locations[i][0] + '</div></a>');
	          infowindow.open(map, marker);
	        }
	      })(marker, i));
	    }
	}
     google.maps.event.addDomListener(window, 'load', initialize);

</script>
		

Replacement Open Layers Map

The code below plots the equivalent map only this time using Open Layers V3.



<link rel="stylesheet" href="./ol_v5.2.0.css"" type="text/css">
<link rel="stylesheet" href="./ol-popup.css"" type="text/css">

<script src="./ol_v5.2.0.js"></script>
<script src="./ol-popup.js"></script>


<script>
	var locations = [
      	["Statue Of Liberty", 40.6892534, -74.0446426, "the-statue-of-libety", "photo-r49243.jpg", 1],
      	["Central Park", 40.7828687, -73.9659076, "central-park", "photo-3122121.jpg", 2],
      	["Rockefeller Center", 40.7562179,-73.9848441, "rockerfeller-center","photo-233444.jpg", 3]
      	];

	// Array of Icon features
	var iconFeatures=[];
	for (var i = 0; i < locations.length; i++) {
	  var iconFeature = new ol.Feature({
	  	type: 'click',
		desc: locations[i][0],
		url: locations[i][3],
		image: locations[i][4], 
	    geometry: new ol.geom.Point(ol.proj.transform([locations[i][2], locations[i][1]], 'EPSG:4326', 'EPSG:3857')),
	  });

	  iconFeatures.push(iconFeature);
	}

	var vectorSource = new ol.source.Vector({
		features: iconFeatures
	});

	// Custom image for marker
	var iconStyle = new ol.style.Style({
	    image: new ol.style.Icon({
	      anchor: [0.5, 0.5],
	      anchorXUnits: 'fraction',
	      anchorYUnits: 'fraction',
	      src: './map-pin.png',
	      scale: 0.15
		    })
	});
	  
	var vectorLayer = new ol.layer.Vector({
	  source: vectorSource,
	  style: iconStyle,
	  updateWhileAnimating: true,
	  updateWhileInteracting: true,
	});

	// Create our initial map view
	var mapCenter = ol.proj.fromLonLat([ -74.0446426, 40.6892534 ]);
	var view = new ol.View({
	  center: mapCenter,
	  zoom: 10
	});

	// Now create our map
	var map = new ol.Map({
	  target: 'map-canvas',
	  view: view,
	  layers: [
	    new ol.layer.Tile({
	      source: new ol.source.OSM(),
	    }),
	    vectorLayer,
	  ],
	  loadTilesWhileAnimating: true,
	});

	var popup = new ol.Overlay.Popup();
	map.addOverlay(popup);

	// Add an event handler for when someone clicks on a marker
	map.on('singleclick', function(evt) {

	    // Hide existing popup and reset it's offset
	    popup.hide();
	    popup.setOffset([0, 0]);

	    // Attempt to find a feature in one of the visible vector layers
	    var feature = map.forEachFeatureAtPixel(evt.pixel, function(feature, layer) {
	        return feature;
	    });

	    if (feature) {
	        var coord = feature.getGeometry().getCoordinates();
	        var props = feature.getProperties();
	        var info = '<a style="color:black; font-weight:600; font-size:11px" href="http://www.somedomain.com/' + props.url + '">' + 
		'<img width="200" src="' +  props.image + '"  />' + 
		'<div style="width:220px; margin-top:3px">' + props.desc + '</div></a>';

	        // Offset the popup so it points at the middle of the marker not the tip
	        popup.setOffset([0, -22]);
	        popup.show(coord, info);
	    }
	});

	// Add an event handler for when someone hovers over a marker
	// This changes the cursor to a pointer
	map.on("pointermove", function (evt) {
	    var hit = map.forEachFeatureAtPixel(evt.pixel, function(feature, layer) {
	        return true;
	    }); 
	    if (hit) {
	        this.getTargetElement().style.cursor = 'pointer';
	    } else {
	        this.getTargetElement().style.cursor = '';
	    }
	});

</script>

		

The plotted map looks as follows -

Open Layers Map

Download Source Code