Project StructureFor this exercise, our custom Google Map demo will live on GitHub (not on CodePen). Here’s the project structure: map/ ├── index.html ├── img/ │ ├── address.svg │ ├── modal-fax.svg │ ├── modal-lat-long.svg │ ├── modal-pin.svg │ ├── modal-tel.svg │ └── pin.svg ├── main.css └── main.js 1. Scaffolding the ProjectBefore we start creating our project (that will look like a mini app) there are a few things that we have to take into consideration. Grab a Google Maps API keyAs a first and mandatory thing, we should get a Google Maps API key. To do so, we need to follow these instructions and set up a project in the Google Cloud Console with the Maps JavaScript API enabled. For this demonstration, we’ll borrow an API key from an old yet still popular series called The Google Maps API For Designers. There’s also an associated demo from where we can extract the API. warning This demo API key has usage limits! Make sure to register for your own API key and replace the one in the example. Last but not least, as soon as you set up such a project in the Google Cloud Console, it’s always wise to restrict the associated API. For example, you might have a single project and an API that you share across all your website clients. In such a case, you can restrict the API requests to specific websites. ![]() ![]() ![]() Grab Some DataTo create the markers and make our project as realistic as possible, we’ll need some real-world data. With this in mind, as previously mentioned, we’ll take 13 of the Adobe office locations and pin them on our map. As we’ll see later, each location needs to include its latitude and longitude. As this info isn’t available on Adobe’s contact page, we’ll use the LangLong.net website to retrieve their coordinates. Some of the coordinates might not be perfectly accurate, but you get the point. Grab Some IconsTo enhance the demo appearance, we’ll need some icons. Envato Elements provides hundreds of different map and navigation icons for our needs. In this case, we’ll go with an icon set that follows a filled line style. As we saw from the project structure, the selected SVG icons will live inside the ![]() ![]() ![]() Here are the SVG icons we’ll use in our project: ![]() ![]() ![]() Include Bootstrap FilesLastly, although not required, to speed up the development process we’ll also include Bootstrap in our project by following the CDN approach, as described on this page. 2. Define the Page MarkupNow that we have everything set up, let’s look at our markup. Required FilesBelow you can see the starting markup with all the required Bootstrap files, our files, and the <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>A simple example showing how to build a stylish Google Map with multiple markers</title> <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous" /> <link rel="stylesheet" href="main.css" /> </head> <body> <!-- content here --> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBSJRUNeSfHkH_ChC38jKTvjc2V7QQcOYs&language=en&callback=initMap" async></script> <script src="main.js"></script> </body> </html> Just take a look at the
Custom Google Map LayoutBefore having a closer look at the page elements, let’s discuss the layout requirements.
![]() ![]() ![]()
![]() ![]() ![]()
Here’s the associated markup filled with Bootstrap helper classes: <div class="container-fluid"> <div class="row align-items-center"> <div class="col-md-6 mt-5 mb-3"> <h1 class="mb-4"> Some of <a href="https://www.adobe.com/about-adobe/contact/offices.html" class="text-body" target="_blank">Adobe's office locations</a> </h1> <div class="block"> <h2 class="mb-3">North America</h2> <div class="row"> <div class="col-sm-6 mb-2"> <div class="d-flex align-items-center"> <img width="24" height="24" src="img/address.svg" alt="" class="me-2" /> <a href="" class="location text-body" data-index="0">Corporate headquarters</a> </div> </div> <div class="col-sm-6 mb-2"> <div class="d-flex align-items-center"> <img width="24" height="24" src="img/address.svg" alt="" class="me-2" /> <a href="" class="location text-body" data-index="1">Los Angeles</a> </div> </div> </div> <hr /> </div> <!-- more blocks here --> </div> <div class="col-md-6 p-0"> <div id="map" class="vh-100"></div> </div> </div> </div> Most importantly, notice two things:
3. Add the JavaScriptAt this point, we’re ready to build the core functionality of our custom Google Map project. Let’s do it! Store LocationsWe captured the locations in the markup, but we also need them in JavaScript. So, let’s store them under an array like this: const pins = [ { location: "North America", name: "Corporate headquarters", address: "345 Park Avenue <br> San Jose, CA 95110-2704", tel: "408-536-2800", fax: "408-537-6000", lat: 37.33078, long: -121.892357, }, { location: "North America", name: "Los Angeles", address: "(former Magento office) <br> 3640 Holdrege Ave <br> Los Angeles, CA 90016", lat: 34.01989, long: -118.37811, }, // more locations here ]; Keep in mind that we preserve the order in which the locations appear both in the markup and object. A location with the Note: in a real-world scenario, there would probably be a backend language to manage all locations in one place. For example, if you’re familiar with WordPress and the ACF PRO plugin, you’ll probably have a flexible content or a repeater field where you put all locations. Inside it, there will be extra fields for managing the location details. Especially for grabbing the coordinates of each location, you can have a Google Map field. Then, via the Initialize Custom Google MapComing up next, we’ll initialize the map through the Our map will have the following customizations:
![]() ![]() ![]() With all the above in mind, here’s the starting body of our function: // London, UK const center = { lat: 51.507351, lng: -0.127758 }; const styles = [ { featureType: "poi", stylers: [ { visibility: "off" } ] }, { featureType: "water", stylers: [ { color: "#39C3FC" } ] } ]; function initMap() { const map = new google.maps.Map(document.getElementById("map"), { center, styles, zoom: 3 }); } Create Google Map MarkersInside the function initMap() { // map declaration here createMarkers(map); } Inside this function, we’ll do the following things:
![]() ![]() ![]()
Here’s the function declaration: function createMarkers(map) { const infowindow = new google.maps.InfoWindow(); const markerIcon = { url: "img/pin.svg", scaledSize: new google.maps.Size(40, 40) }; for (let i = 0; i < pins.length; i++) { const marker = new google.maps.Marker({ position: { lat: pins[i].lat, lng: pins[i].long }, map, icon: markerIcon, animation: google.maps.Animation.DROP }); markers.push(marker); } } Toggle Info WindowInside the function createMarkers(map) { ... for (let i = 0; i < pins.length; i++) { // marker here google.maps.event.addListener(marker, "click", function () { infowindow.setContent(createInfoWindowContent(pins[i])); map.setCenter(marker.getPosition()); infowindow.open(map, marker); const targetLocation = document.querySelector(`[data-index="${i}"]`); if (document.querySelector(".location.active")) { document .querySelector(".location.active") .classList.remove(activeClass); } targetLocation.classList.add(activeClass); scroll({ top: targetLocation.offsetTop, behavior: "smooth" }); }); } } Each time a user clicks on a marker, we’ll perform the following actions:
![]() ![]() ![]()
Populate Info WindowAs we said, the job of the We’ll use straightforward markup to display the contents of each marker. Given that some locations don’t always have all the details, we’ll apply some checks to ensure that our markup won’t be bloated. ![]() ![]() ![]() Here’s the function declaration: function createInfoWindowContent(pin) { let phoneString = ""; let faxString = ""; let latLongString = ""; let addressString = ""; if (pin.tel) { phoneString = ` <p class="d-flex align-items-center"> <img class="me-2" width="24" height="24" src="https://webdesign.tutsplus.com/tutorials/img/modal-tel.svg" alt=""> ${pin.tel} </p> `; } if (pin.fax) { faxString = ` <p class="d-flex align-items-center"> <img class="me-2" width="24" height="24" src="img/modal-fax.svg" alt=""> ${pin.fax} </p> `; } if (pin.lat && pin.long) { latLongString = ` <p class="d-flex align-items-center"> <img class="me-2" width="24" height="24" src="img/modal-lat-long.svg" alt=""> ${pin.lat}, ${pin.long} </p> `; } if (pin.address) { addressString = ` <div class="d-flex"> <img class="me-2" width="24" height="24" src="img/modal-pin.svg" alt=""> ${pin.address} </div> `; } const contentString = ` <h3 class="fs-4 text">${pin.name}</h3> <hr> ${phoneString} ${faxString} ${latLongString} ${addressString} `; return contentString; } Location LinksWe discussed what should happen when a marker is clicked. But we also need to apply some functionality when the opposite happens. In other words, we want to ensure that each time a user clicks on a location link, the corresponding marker will be clicked. Another function, the So, each time a location link is clicked, we’ll perform the following actions:
Here’s the function definition: function showLocations() { const locations = document.querySelectorAll(".location"); locations.forEach((location) => { location.addEventListener("click", function (e) { e.preventDefault(); if (document.querySelector(".location.active")) { document .querySelector(".location.active") .classList.remove(activeClass); } location.classList.add(activeClass); scroll({ top: document.getElementById("map").offsetTop, behavior: "smooth" }); new google.maps.event.trigger(markers[this.dataset.index], "click"); }); }); } ConclusionAnd we’re done! This was quite a long journey, but I hope that you enjoyed it and that it has helped enhance your skills regarding the Google Maps JavaScript API. Once again, don’t forget to put your own key for live project testing! Here’s the project link. Things don’t stop here. We can continue enhancing/extending this project by doing a number of things, for instance:
![]() ![]() ![]() As always, thanks a lot for reading! via Pixel Lyft https://ift.tt/EJ2nPzy
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. Archives
April 2023
Categories |