If you’ve done anything on the web in any capacity, you’ve undoubtably had to use a Google Map in some fashion.
Generally, this involves creating a JavaScript Map object with various properties and the location’s lat long coordinates, then passing it to an empty div to render the map.
Oh, you need more than one instance per page? Well, then create a second instance with a unique div. Rinse repeat for any other required maps. A tad lame, especially for simple, single marker maps.
Wouldn’t it be nice to have an address/vCard in your markup render each map instance automatically? Of course it would. No more lat long lookups. No more creating additional javascript for each map. Just some vCards defined in your html doc.
The Run Down
With a bit Jquery, let’s make it happen captain. Here’s a quick run down of what we’re going to do.
- Define a reusable class to house our maps.
- Write the Jquery that will parse the vcard text so Google Maps can find and map the location.
- Define some global map controller options.
- Ensure that our Jquery only runs on pages with maps to prevent console errors.
- Add our required css for map rendering.
- Include the google maps api script on our map page.
- Add our vcards to the page.
- Snazzy up our google maps with custom stylers.
The Jquery
First, let’s define a reusable class called .js-maps
to house our maps. Next, we’ll write some Jquery to locate and build the map by parsing the text from our vCard addresses (in addition to setting the map’s zoom).
While we’re at it, let’s also establish a variable for some custom stylers (more on that in a bit) and make sure our marker stays centered on resize. Then, let’s define some options for our Map’s controls ( i.e. map type, map UI, scroll wheel support, custom styles, etc. Check Google Maps docs for a list of controllers).
Finally, to prevent console errors for pages without the Google Maps api script, best to make sure our maps exist with a simple if ($(".js-map").length) {}
check.
//Do maps exist?
if ($(".js-map").length) {
$(function() {
//Stylers array
var styles = [];
// Render to
$maps = $('.js-map');
$maps.each(function(index, Element) {
$vcardGmap = $(Element).children('.vcard-gmap');
// Map vars
var map;
var geocoder;
var marker;
var infowindow;
var address =
$vcardGmap.children('.address').text() + ', '
+ $vcardGmap.children('.city').text() + ', '
+ $vcardGmap.children('.state').text() + ' '
+ $vcardGmap.children('.zip').text() + ', '
+ $vcardGmap.children('.country').text();
//Info Window Content
var content =
$vcardGmap.children('.location').text() + '
' +
$vcardGmap.children('.address').text() + '
' +
$vcardGmap.children('.city').text() + ' ' +
$vcardGmap.children('.state').text() + ' ' +
$vcardGmap.children('.zip').text();
//If available, add a phone number to the info window
if (0 < $vcardGmap.children('.phone').text().length) {
content += '
' + $vcardGmap.children('.phone').text();
}
geocoder = new google.maps.Geocoder();
// Geocode the Address
geocoder.geocode({'address': address}, function(results, status) {
// Status check
if (status === google.maps.GeocoderStatus.OK) {
vcardGmapOptions.center = results[0].geometry.location;
map = new google.maps.Map(Element, vcardGmapOptions);
// Custom Marker options
marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
animation: google.maps.Animation.DROP,
//icon: 'images/yourdopemarker.png',
title: $vcardGmap.children('.location').text()
});
//Create tile/info window
infowindow = new google.maps.InfoWindow({'content': content});
google.maps.event.addListener(map, 'tilesloaded', function(event) {
infowindow.open(map, marker);
});
//Click marker to open tile
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker);
});
//Center on Resize
google.maps.event.addDomListener(window, "resize", function() {
var center = map.getCenter();
google.maps.event.trigger(map, "resize");
map.setCenter(center);
});
} else {
// Alert if map fails
alert('damn, the google maps failed yo: ' + status);
}
});
/*----------------------------------------------
--Control Options
----------------------------------------------- */
var vcardGmapOptions = {
//Let's establish zoom control in our vcard markup
'zoom': parseInt($vcardGmap.children('.zoom').text()),
'mapTypeId': google.maps.MapTypeId.ROADMAP,
'mapTypeControl': false,
'scrollwheel': false,
'disableDefaultUI': false,
'styles': styles
};
});
});
}
A Little CSS
With our js set up, we’ll need a few basic styles for the map to render properly. On mobile, you might also want to include a transparent overlay so you can scroll down the page, not the map itself. Additionally, let’s hide a few of the elements added by google (sorry guys).
/*----------------------------------------------
--GMaps
----------------------------------------------- */
.js-map {
height: 100%;
min-height: 30em;
margin: 0;
padding: 0;
/*-------------------------------------------
--Overlay for mobile scrolling
---------------------------------------------*/
&::after{
@media (max-width: $mq-med) {
content: '';
position: absolute;
top: 0;
width: 100%;
height: 100%;
z-index: 99;
background: transparent;
}
}
/*-------------------------------------------
--Info Window / Popup
---------------------------------------------*/
.gm-style-iw > div{
font-size: 1.2em;
overflow: hidden;
height: auto;
line-height: 1.6;
}
/*-------------------------------------------
--Hide some of the Google inserted stuff
---------------------------------------------*/
.gmnoscreen,
.gm-style-cc {
display: none !important;
}
}
Address Blocks / vCards
Time to create our page now. First, make sure to add the Google Maps API script (And, don’t forget Jquery lil buddy).
<script type='text/javascript' src='https://maps.googleapis.com/maps/api/js?sensor=false&ver=1'></script>
Now, add our Address vCards, following the syntax set up in our JS. Make sure to add a .zoom
div to declare your maps initial zoom level.
<article class="js-map">
<div class="vcard-gmap">
<span class="location">Urban Influence</span>
<span class="address">1508 10th Ave</span>
<span class="city">Seattle</span>
<span class="state">WA</span>
<span class="zip">98122</span>
<span class="country">USA</span>
<span class="phone">310-543-0375</span>
<span class="zoom">11</span>
</div>
</article>
Boom. Sit back and watch your vCard magically transform into a Google Map. For multiple maps, just add another vCard.
Wait! What about custom map styles?
Oh yeah right. Good catch. Remember that styles variable we included in our Jquery? Let’s do something with it. Google Maps permits full control over the visual display of your map and such elements as roads, geography, regions, etc.
Styled maps use two concepts to apply colors and changes to a map:
1. Map features – the geographic elements and their labels.
2. Stylers – the color and visibility properties that can be applied to map features, defined through a combination of hue, color, and lightness/gamma values.
Map features and stylers are combined into a style JSON array, which is passed to the default map’s MapOptions
object, or to the StyledMapType
constructor. The array takes the following form:
var stylesArray = [
{
featureType: '',
elementType: '',
stylers: [
{hue: ''},
{saturation: ''},
{lightness: ''},
// etc...
]
},
{
featureType: '',
// etc...
}
]
Snazzy Maps
Instead of writing your JSON array by hand, there are a few nice tools that provide a visual interface. MapBuildr is top notch. But, I prefer Snazzy Maps. You can puruse a range of ready-to-rock styles, or roll a custom one from scratch. Just copy the JSON output and add it your style varable.
Demo?
Of course. Here’s a little demo