Streaming live at 10am (PST)

Google Maps with Multiple locations and CMS

Feel free to use it!

Thanks,

Renan

3 Likes

This, Sir, is amazing. You’re a rockstar !!! :metal:t2:

Do you know though if it’s possible to open the markers when clicking on the lists elements under the map ? Currently it just reloads the maps, which is probably not what you intended to do with it.

Also ave you tried if this solution is compatible with the marker-clustering in Maps ?

2 Likes

Hello @Pasint, thank you. Actually I did this long time ago, It was supposed to work like you said (when click on the car, scroll up to the map and open the modal). But I’m not sure why isn’t working right now. Maybe some JS will do the job…

About marker-clustering - no I didn’t. Sorry for that.

Renan

@Renan_M_falo, I’ve sent you a PM. Lemme know what you think.

This is awesome! Could you make a video explaining the steps? When I open the Webflow project, there is no map embed or modal… so I’m not sure how you did this.

1 Like

Wow!!! this is really great!!! I’m having a little hard time to implement it since I’m no coder, can you explain it a little bit how this works?

1 Like

Circling back to this in 2020. The paid solutions for this functionality are like $30/mo, which is ridiculous. If you shoot a quick walkthrough demonstrating how to implement this, it would be huge!

If not, no worries!

Cyan

Hi @Cyan, I managed to get a solution for this to work here.
I don’t remember if the setup is similar to Renan’s as it’s been a while, but it works for me. If that’s the way you want it to work, I can share the info.
Let me know…

Hey @Pasint, this is great, I would be very interested to see how you built it!

What I am trying to create is this: https://www.travishyde.com/ (Scroll to the bottom to see the map)

Using your method, would it be possible to include all the same type of information you see when you click on one of those map pins? (Address, URL, phone number, etc.)

I’m not sure if it’s the est way to share all this, but I’ll try here…

1. Page setup
Make sure to name your elements properly.
image

2. CMS setup
I use 2 Collections here, one for list of members and one for member categories. Categories are then pulled into members info with a reference element. For me the map pin images are saved in the Categories.
To point members on the map, you’ll need latitude and longitude elements.
image

3. Calling CMS data on page
You’ll need a Collection on the page calling the data from the CMS. The map will need this ‘on page’ data to be populated. Once created, you can hidde this Collection using ‘display : hidden’. It’s what I did.
image

4. Script calling CMS data
Inside your Collection, you’ll have the following script calling your data
image

Here’s the actual script you can copy:

<div class="bg-pic-membre" style="background: url('CMS ELEMENT') center/cover no-repeat"></div>

<script>
membres.push({
  'name'  : 'CMS ELEMENT',
  'slug'  : 'CMS ELEMENT'',
  'url'   : 'CMS ELEMENT'',
  'lat'   : 'CMS ELEMENT'',
  'lng'   : 'CMS ELEMENT'',
  'pin'   : 'CMS ELEMENT'',
  'photo' : 'CMS ELEMENT',
  'category' : 'CMS ELEMENT'',
  
});
</script>

5. Script for page
Finally, you’ll need to add the following scripts to the header and footer sections of your page. You’ll find the full scripts below so you can copy paste.

Inside head tag

<script>
// Array to store all members on page. Do not remove!
var membres = [];
</script>

<style>
#map_wrapper {
  height: 720px;
}
#map_canvas {
  display: block;
  width: 90%;
  height: 100%;
  margin-left: auto;
  margin-right: auto;
}
.bg-pic-membre {
  max-width:100%;
  min-height:300px;
  background-size:cover;
}
#map_canvas .bg-pic-membre {
  min-height: 0;
  height: 80px;
  margin-bottom: 5px;
}

@media screen and (min-width: 1200px) {
  .w-container {
    max-width: 1400px;
  }
}

@media screen and (max-width: 1280px) and (min-width:1025px) {
  .dynamic-item-membre {
    width: 31.8%!important;
  }
  .w-container {
    max-width: 1240px;
  }
  h1 {
    font-size: 31px!important;
  }
}

@media screen and (max-width:1024px) and (min-height:768px) {
  .dynamic-item-membre {
    width: 47.5%!important;
  }
  .container-header-page {
    padding:0px!important;
  }
}
</style>

Before body tag

<script src="https://maps.googleapis.com/maps/api/js?sensor=false&callback=initialize&key=YOUR-MAP-API-KEY" async defer></script>
<script>
// Variables for Google maps
var map, mapElem, markerImg, infoWindow, marker;
var markers = [], infoWindows = [];
var mapOptions = {
  mapTypeId: 'roadmap',
  //zoom: 13,
  //scrollwheel: false,
};

function initialize() {
  markerImg = {
    //url:  'https:// YOUR-PIN-IMAGE.png',
    size: new google.maps.Size(50, 50),
    anchor: new google.maps.Point(23, 54),
  }

  // Display a map on the page
  mapElem = document.getElementById('map_canvas');
  map = new google.maps.Map(mapElem, mapOptions);
  map.setTilt(45);

  // Loop through our array of members
  for(i = 0; i < membres.length; i++) {
    var membre = membres[i];

    // Generate an infowindow content for the marker
  	var infoWindow = new google.maps.InfoWindow();
    infoWindow.setContent(

      '<a href="https://cdp-maquette-v2.webflow.io/membres/'+membre.url+'"><div class="bg-pic-membre" style="background:url('+membre.photo+') center/cover no-repeat"></div></a>' +
      '<a href="https://cdp-maquette-v2.webflow.io/membres/'+membre.url+'"><h3 class="c-membreblock_title">'+membre.name+'</h3> <p class="c-membreblock_title subtitle">'+membre.category+'</p></a>'

    );
    infoWindows.push(infoWindow);

    // Place a marker on the map
    createMarker(membre.lat, membre.lng, i);
  }

  // Center the map fitting all markers on the screen
  fitToMarkers();
}

function createMarker(x, y, i) {
  marker = new google.maps.Marker({
    map: map,
    icon: membres[i].pin,
    position: new google.maps.LatLng(x,y),
    title: membres[i].name
  });
  marker._index = i;
  markers.push(marker);

  // Click event on marker
  google.maps.event.addListener(marker, 'click', (function(marker, i) {
    return function() {
      // Close last opened infowindow if any
      if(infoWindow) infoWindow.close();
      // Open clicked infowindow
      infoWindow = infoWindows[i];
      infoWindow.open(map, marker);
    }
  })(marker, i));
}

function mapResize() {
  google.maps.event.trigger(map, "resize");
  fitToMarkers();
}

function fitToMarkers() {
  map.setZoom(15);
  var bounds = new google.maps.LatLngBounds();
  for(var i = 0; i < markers.length; i++) {
   bounds.extend(markers[i].getPosition());
  }
  map.fitBounds(bounds);
  map.setZoom(14); // zoom out when done so markers on the top can be seen
}

// When Webflow has loaded,
Webflow.push(function() {

	// Resize event
  $(window).resize(function() {

    // Do nothing if mobile
    if($(window).width() < 768) return;

    // Resize map if function is defined
    if(typeof mapResize === 'function') mapResize();
  });
});
</script>
2 Likes

Just to confirm, this is indeed using @Renan_M_falo solution. I take no credit here, it’s all thanks to his solution.

And to answer your last question @Cyan, I think it’s possible to the information you want when clicking on the map pin.
You’ll need to configure the “infowindow” element properly in the code 'Before Body Tag, and make sure you have all the info you need pulled from the CMS in the script that’s inside the Collection.

1 Like

Thank you for taking the time to write this out! I will try implementing and let you know how it goes!

1 Like