Concrete5 features a handy Google Maps block to quickly add a map to your site. The default look of Google Maps isn't ugly, but it might not quite fit with your theme - here's how to customise the appearance.

Note: this tutorial is for version 5.6 of concrete5.  

For version 5.7, only the block's view.php file needs to be overridden, in which you'll find the mapOptions array where you can add custom styles.

Fortunately Concrete5 uses version 3 of Google's map API, which means that embedded maps can be customised in a variety of ways, including the colours used and the visibility of items. Also, it's only a quick override to the Google Maps block, which isn't hard to do.

Override the controller

The first thing to do is create a folder in concrete5's top level blocks folder called google_map.

Into this folder, copy the controller.php file from /concrete/blocks/google-map/
It's actually very small file only has three lines in it.

If you're new to concrete5 overrides, you might be wondering where all the code is for the block. The way concrete5 has been structured is that block controller classes inherit their functions from another 'core' class for the block. This means that the individual functions of the class can be overriden, without having to override all the functions of the controller class (as was the case in the past).

In this case, we want to override the on_page_view function in the controller as this is where we need to adjust the parameters used to initialise the google map. The 'core' class for the google maps block can be found at /concrete/core/controllers/blocks/google_map.php

In this file, find the on_page_view function and copy it into your top level /blocks/google_map/controller.php file, in-between the existing braces. It'll end up looking like this:

<?php 
	defined('C5_EXECUTE') or die("Access Denied.");
	class GoogleMapBlockController extends Concrete5_Controller_Block_GoogleMap {
		
		public function on_page_view() {
			$html = Loader::helper('html');
			$c = Page::getCurrentPage();
			if (!$c->isEditMode()) {
				$this->addFooterItem('<script type="text/javascript" src="//maps.google.com/maps/api/js?sensor=true"></script>');
				$this->addFooterItem('<script type="text/javascript"> 
				function googleMapInit' . $this->bID . '() { 
				   try{
					  var latlng = new google.maps.LatLng(' . $this->latitude . ', ' . $this->longitude . ');
					   var mapOptions = {
						 zoom: ' . $this->zoom . ',
						 center: latlng,
						 mapTypeId: google.maps.MapTypeId.ROADMAP,
						 streetViewControl: false,
						 mapTypeControl: false
					  };
					   var map = new google.maps.Map(document.getElementById(\'googleMapCanvas' . $this->bID . '\'), mapOptions);
					   var marker = new google.maps.Marker({
						   position: latlng, 
						   map: map
					   });
				   }catch(e){
				   $("#googleMapCanvas'. $this->bID .'").replaceWith("<p>Unable to display map: "+e.message+"</p>")}
				}
				$(function() {
					var t;
					var startWhenVisible = function (){
						if ($("#googleMapCanvas'. $this->bID .'").is(":visible")){
							window.clearInterval(t);
							googleMapInit' . $this->bID . '();
							return true;
						} 
						return false;
					};
					if (!startWhenVisible()){
						t = window.setInterval(function(){startWhenVisible();},100);      
					}
				});            
				</script>');				
			}
		}
		
	}

This code is responsible for outputting the scripting needed to initialise the google map - we'll adjust this to change a few settings.

What we specifically want to look at is this Javascript object:

var mapOptions = {
   zoom: ' . $this->zoom . ',
   center: latlng,
   mapTypeId: google.maps.MapTypeId.ROADMAP,
   streetViewControl: false,
   mapTypeControl: false
};

It's in this object that we can add in further options and adjust the map. It doesn't just have to be the appearance by the way, there are additional options we can set

For example, we might want to prevent the mousewheel from scrolling the map (a problem if you have a large map), so we'd change the mapOptions to the following:

var mapOptions = {
   zoom: ' . $this->zoom . ',
   center: latlng,
   mapTypeId: google.maps.MapTypeId.ROADMAP,
   streetViewControl: false,
   mapTypeControl: false,
   scrollwheel: false
};

Create your style rules

One of the options we can set is the 'styles' option - this requires an array of information to specify the map elements we want to change. Although this format isn't overly difficult to understand, it's still quite complex. Fortunately, Google have made available an online tool that allows you to change the colours and options for each of the different map elements

Persevere with this tool - select something in the top left, style it and add it using the button on the right. Repeat for each map element you want to change. Finally, use the Show JSON button to export your style settings.

The result of this tool is that you can generate some JSON code, which is then used as the value for the 'styles' option.  A suggestion here is to first create a variable to hold your styles, passing that into the mapOptions object:

var styles = [];

var mapOptions = {
   zoom: ' . $this->zoom . ',
   center: latlng,
   mapTypeId: google.maps.MapTypeId.ROADMAP,
   streetViewControl: false,
   mapTypeControl: false,
   styles: styles
};

Add the style rules to your controller override

Then simply copy and paste your generated JSON code instead of the square brackets, e.g:

var styles = [
 {
   "featureType": "road.arterial"  },{
   "featureType": "landscape.man_made",
   "stylers": [
     { "color": "#F6F6F6" }
   ]
 },{
   "featureType": "road.local",
   "elementType": "geometry",
   "stylers": [
     { "hue": "#EEEBC6" },
     { "color": "#acadad" }
   ]
 },{
   "featureType": "road.highway",
   "elementType": "geometry",
   "stylers": [
     { "lightness": 35 },
     { "color": "#a91e2f" }
   ]
 },{
   "featureType": "administrative",
   "stylers": [
     { "visibility": "off" }
   ]
 },{
   "featureType": "landscape.natural",
   "stylers": [
     { "color": "#F6F6F6" }
   ]
 },{
   "featureType": "poi",
   "stylers": [
     { "visibility": "off" }
   ]
 },{
   "featureType": "water",
   "stylers": [
     { "visibility": "on" },
     { "color": "#2B6DAD" }
   ]
 }
];

var mapOptions = {
   zoom: ' . $this->zoom . ',
   center: latlng,
   mapTypeId: google.maps.MapTypeId.ROADMAP,
   streetViewControl: false,
   mapTypeControl: false,
   styles: styles
};

With this in place, a placed Google Map should appear as per your styling. I've use the above on our site, with this result:
 

You may need to clear your cache to have this kick in. This kind of override will affect all map blocks you've placed on your site.

-Ryan