Use Google Maps with Rails - LPC-Ltda/Ruby-on-Rails GitHub Wiki
Los mapas son la forma de navegar el mundo. Ellos nos dan la habilidad de inspeccionar cada ubicación única en la tierra, abriendo el camino a servicios como el ruteo y la composición del suelo. En este artículo, iré a través del API de Goolgle Maps (y algunos alternativos) y los integraré con Rails.
El código fuente está disponible en un repositorio Github. Cada característica es un commit separado, así usted podrá seguir el avance del tutorial usando git checkout.
Pre-requisitos
Conocimiento básico de Ruby usando RailsBrick.
Conocimiento intermedio de JavaScript
Cómo funcionan los mapas en la web. Este artículo es una buena lectura si usted es nuevo en el juego.
Nuestro objetivo es hacer simple la integración de mapas con Rails. Este tutorial va a través de los pasos exactos para integrar Google Maps, cubriendo algunas gemas de Rails útiles. Finalmente, alternativas a Google Maps, como el popular librería de código abierto Leaflet.js y MapBox, a las que daremos una breve mirada.
En el pasado, Google Maps requería una llave API, sin embargo esta llave API no es obligatoria en V3. Si usted está usando otra versión, siga estos pasos:
Si usted usa Googe Maps V3 saltese esta parte
- Vaya a la consola API de Google
- Clickee en APIs & auth -> APIs.
- Activar Google Maps JavaScript v3 al clickear el botón status para que esté en On.
- Clickear en credentials -> Create key -> browser key
- Asegúrese que ACCEPT REQUESTS FROM THESE HTTP REFERERS (WEB SITES) esté vacío o contenga su dominio, como en la imágen a continuación.
NOTA: Not todos los aspectos del mapa están cubiertos en el material que sigue. Para una información más detallada, usted puede visitar la documenttación Google Maps JavaScript.
Cargando el Mapa
Primero, crear el proyecto con RailsBrick (Usted es libre de usar cualquier herramienta para crear aplicaciones rails). Este es un creador de aplicaciones rails con funcionalidad básica. Usted puede ver como utilizarlo en un vídeo introductorio que se obtiene aquí.
Para inicializar el mapa en su home page, cree un div con un id map-canvas
en el view del home (/app/views/home.erb). Envuelva esta div en otro con el id map-container
, el cual será usado para darle algo de estilo al mapa.
Primero: Aquí está el código para al view del home
<% title("Home Page") %>
<h1>Google Maps Tut</h1>
<div id="map-container">
<div id="map-canvas"></div>
</div>
Agregar algo de CSS. Abrir el archivo llamado frameworkandoverrides.css.scss, el cual es parte de RailsBrick y es usado para sobre-escribir los estilos Bootstrap.
Segundo: Agregue los siguientes estilos:
#map-container {
height: 400px;
border-radius: 16px 16px;
border-color: #fff;
border-style: solid;
box-shadow: 2px 2px 10px #B1B1B1;
margin-top: 25px;
border-width: 7px;
}
#map-canvas {
height: 384px;
width: 100%;
}
Como usted puede ver en el CSS arriba, seteamos el map-container
con un alto fijo de 400 pixeles y agregamos algún estilado del borde. El paso final para tener un mapa que trabaja inicial es crear una carpeta llamada "map" en app/assets/javascript/map y agregar un archivo llamado gmap.js. Ahora el mapa debe lucir como esto:
NOTE: Si el controlador del zoom del mapa no se muestra apropiadamente, es un conflicto con los estilos de Bootstrap para imágenes y etiquetas. Sólo agregue esta re-escritura un su archivo CSS (frameworkandoverrides.css.scss):
/* Bootstrap Css Map Fix*/
#map-container #map-canvas img {
max-width: none;
}
/* Bootstrap Css Map Fix*/
#map-container #map-canvas label {
width: auto; display:inline;
}
Basic markers
El API Google Maps contiene un objeto marcador (marker) que le permite crear fácilmente marcadores. El objeto marcador contiene atributos como marker position, market title, y el mapa donde el marcador es ubicado.
Para eliminar la repetición de código, cree una función llamada createMarker con los parámetros cords, map, y título:
var marker;
function createMarker(coords, map, title){
marker = new google.maps.Marker({
position: coords,
map: map,
title: title
});
}
Marcadores personalizados
El objeto marcador es un atributo "icon" el cual puede tomar un path o objeto imágen. Crearemos dos funciones: una para crear una imagen y otra para crear un marcador personalizado. Para hacer el marcador arrastrable, simplemente agregue el atributo draggable
con el valor true
. También, el API Google Maps soporta dos tipos de animación para el marcador: DROP
y BOUNCE
.
Create a function named createImage which will return the image object used by our custom marker. Its size is 32×32 pixels and its origin is (0, 0).
1 2 3 4 5 6 7 8 9 10 11 12 function createImage(url){ var image = { url: url, // This marker is 32 pixels wide by 32 pixels tall. size: new google.maps.Size(32, 32), // The origin for this image is 0,0. origin: new google.maps.Point(0,0), // The anchor for this image is the base of the flagpole at 0,32. anchor: new google.maps.Point(0, 32) }; return image; } Next, create a function called createCustomMarker to do the actual work of creating the marker object. It takes the coords, the map object, and the title for the marker. Use the function createImage to return the correct image for our icon.
1 2 3 4 5 6 7 8 function createCustomMarker(coords,map,title){ marker = new google.maps.Marker({ position: coords, map: map, title: title, icon: createImage("/assets/icon.png") }); } Infowindow
Infowindow is a tooltip for displaying content (text or images). You can add an infowindow to a marker or on a specified longitude and latitude (lon, and lat for short). The InfoWindow object takes a InfoWindowOptions object.
1 2 3 4 5 6 function createInfoWindow(text){ var infowindow = new google.maps.InfoWindow({ content: text }); return infowindow; } Put the following code in an initialize() function
1 2 3 4 5 // add infowindow when clicking on the simple marker marker var info = createInfoWindow("Congratulations!"); google.maps.event.addListener(marker, 'click', function() { info.open(map,marker); }); This code will create an Infowindow named info and place the text “Congratulations!” in it. An event listener handles the click event on the marker to open the Infowindow.
Drawing simple and custom marker
Drawing lines
Drawing lines requires a series of coordinates to connect. The Google Maps API provides an object called Polyline for drawing lines with attributes stroke_color, weight, and opacity, along with adding icons, symbols, or animation.
Simple Line
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // drawing static polyline var lineCoordinates = [ new google.maps.LatLng(30.055487, 31.279766), new google.maps.LatLng(30.223356, 31.324345), new google.maps.LatLng(30.345656, 31.567677), new google.maps.LatLng(30.565678, 31.676887) ]; createPolyline(map, lineCoordinates, lineSymbol);
var linePath; function createPolyline(map,lineCoordinates,lineSymbol){ linePath = new google.maps.Polyline({ path: lineCoordinates, geodesic: true, strokeColor: '#FF0000', strokeOpacity: 1.0, strokeWeight: 2 }); linePath.setMap(map); } We define an array called lineCoordinates with the coords for the polyline. The function createPolyline actually creates the polyline, setting its path using the lineCoordinates array. The geodesic attribute is true, telling Google Maps to take care of the complicated math for us. Give it a stroke color of #FF0000, an opacity of 1, and a stroke weight of 2 to make it visible. After we have our polyline object ready, add it to the map using the setMap function.
Simple Line with Dashes.
Drawing a dashed line is simply a matter of creating the style and telling the line to use it. Below, the lineSymbol variable is added to the polyline. Notice that the lineSymbol has a path to follow and a scale of 4. The createPolyline function is modified to use lineSymbol as a repeated icon.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 var lineSymbol = { path: 'M 0,-1 0,1', scale: 4, strokeOpacity: 1, strokeColor: '#393' };
// modify the createPolyline function to contain the symbol var linePath; function createPolyline(map, lineCoordinates, lineSymbol){ linePath = new google.maps.Polyline({ path: lineCoordinates, geodesic: true, strokeColor: '#FF0000', strokeOpacity: 1.0, strokeWeight: 2, icons: [{ // this Array is for adding symbols to the line icon: lineSymbol, offset: '100%' }] }); linePath.setMap(map); } Animated Dashes
We can even animate the dashes by adding a function called animateCircle that moves the icons along the line by changing the offset. There isn’t even a need to change the createPolyline function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 function animateCircle() { var count = 0; window.setInterval(function() { count = (count + 1) % 200;
var icons = linePath.get('icons');
icons[0].offset = (count / 2) + '%';
linePath.set('icons', icons);
}, 20); }
//modify the createPolyline
function to be like the following
var linePath;
function createPolyline(map, lineCoordinates, lineSymbol){
linePath = new google.maps.Polyline({
path: lineCoordinates,
geodesic: true,
strokeColor: '#FF0000',
strokeOpacity: 1.0,
strokeWeight: 2,
icons: [{ // this Array is for adding symbols to the line
icon: lineSymbol,
offset: '0',
repeat: '20px'
}]
});
linePath.setMap(map);
}
Then call the animateCircle() function after creating the polyline with createPolyline function.
User-Created Dynamic Polyline
In the following code, we add the polyline options/attributes to a variable and use it to create the polyline. This is not very different from the above code samples. Adding a click event listener to the map that adds a point to our line allows the user to draw at will.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // drawing dynamic polyline var polyOptions = { strokeColor: '#000000', strokeOpacity: 1.0, strokeWeight: 3 }; poly = new google.maps.Polyline(polyOptions); poly.setMap(map); google.maps.event.addListener(map, 'click', addLatLng);
function addLatLng(event){ var path = poly.getPath(); // Because path is an MVCArray, we can simply append a new coordinate // and it will automatically appear. path.push(event.latLng); } Drawing simple and animated lines
Drawing Polygons
Polygons are similar to polylines in that they are drawn by a series of coordinates. A Polygon has a stroke and fill, which can be customized. We will add the coords for the polygon by hand in an array called polygonCoords and pass it to a new function named drawingPolygon. This function creates the polygon and set its paths to the coords added in the polygonCoords array. Polygons are also draggable and editable.
Simple Polygon
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // drawing polygon var polygonCoords = [ new google.maps.LatLng(30.055487, 31.279766), new google.maps.LatLng(30.466465, 31.118292), new google.maps.LatLng(30.321384, 31.75737), new google.maps.LatLng(30.055487, 31.279766) ];
// Construct the polygon. drawingPolygon(polygonCoords);
function drawingPolygon(polygonCoords) { var polygon = new google.maps.Polygon({ paths: polygonCoords, strokeColor: '#FF00FF', strokeOpacity: 0.8, strokeWeight: 2, fillColor: '#FF0000', fillOpacity: 0.35, draggable:true, editable: true }); polygon.setMap(map); } Drawing polygon
Drawing on the Map Using Drawing library
The Google Maps API supports a drawing library that provides a graphical interface. This GUI lets users draw polylines, polygons, circles, markers, and triangles on the map.
To load the drawing library on the map, just make the maps API URL include &libraries=drawing and start using the DrawingManager object.
The API source link should look like this:
1 https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=drawing Initialize the DrawingManager object:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 // trying the drawing liberary var drawingManager = new google.maps.drawing.DrawingManager({ drawingMode: null, drawingControl: true, drawingControlOptions: { position: google.maps.ControlPosition.TOP_CENTER, drawingModes: [ google.maps.drawing.OverlayType.MARKER, google.maps.drawing.OverlayType.CIRCLE, google.maps.drawing.OverlayType.POLYGON, google.maps.drawing.OverlayType.POLYLINE, google.maps.drawing.OverlayType.RECTANGLE ] }, markerOptions: { icon: "/assets/icon.png" } }); drawingManager.setMap(map); The DrawingManager constructor allows you to manage the map drawing tools (controls) by specifying which overlay will be rendered, its position on the map, and its initial state. Setting drawingMode to null means it will not be defaulted to a specific overlay control. It can be defaulted with the polyline overlay by changing null to google.maps.drawing.OverlayType.POLYLINE.
The second argument is drawingControl which takes true for rendering the control or false for hiding it. drawingControlOptions specifies the control position on the map. Google Maps provides various places to put its controls, such as TOP_CENTER, TOP_RIGHT, BOTTOM_LEFT, and so on.
The arguments also specify the available drawingModes, an array of available google.maps.drawing.OverlayType constants like CIRCLE, POLYLINE, POLYGONS, RECTANGLE, MARKER. You can also give each overlay specific properties, just like we did in the previous code snippets.
The last step is to set the map on drawingManager.
Drawing markers, polylines, polygons, circles and triangles by Drawing library
Adding Map Services
Geocoding and Reverse Geocoding
The Google Maps API provides a class called Geocoder for getting coordinate locations of known addresses (geocoding) and vice-versa (reverse geocoding) dynamically.
While the service no longer requires an API key, it does limit geocodes to 2,500 per day and requires that the resulting application show data with a Google Map. The returned data is either JSON or XML.
1
2
3
4
5
6
7
var geocoding = new google.maps.Geocoder();
Here, we get the coordinates by entering an address into an input field.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function codeAddress(geocoding){ var address = $("#search_box_geocoding").val(); if(address.length > 0){ geocoding.geocode({'address': address},function(results, status){ if(status == google.maps.GeocoderStatus.OK){ map.setCenter(results[0].geometry.location); var marker = new google.maps.Marker({ map: map, position: results[0].geometry.location }); } else { alert("Geocode was not successful for the following reason: " + status); } }); } else { alert("Search field can't be blank"); } } Geocoding
Get Address by Reverse Geocoding
In this case, we pass the latlng variable to the geocode object to generate the location (address) on the map.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 function codeLatLng(geocoding) { var input = $('#search_box_reverse').val(); console.log(input);
var latlngbounds = new google.maps.LatLngBounds(); var listener; var regex = /([1-9])+.([1-9])+,([1-9])+.([1-9])+/g; if(regex.test(input)) { var latLngStr = input.split(",",2); var lat = parseFloat(latLngStr[0]); var lng = parseFloat(latLngStr[1]); var latLng = new google.maps.LatLng(lat, lng); geocoding.geocode({'latLng': latLng}, function(results, status) { if (status == google.maps.GeocoderStatus.OK) { if(results.length > 0) { //map.setZoom(11); var marker; map.setCenter(results[1].geometry.location); var i; info = createInfoWindow(""); for(i in results){ latlngbounds.extend(results[i].geometry.location); marker = new google.maps.Marker({ map: map, position: results[i].geometry.location });
google.maps.event.addListener(marker, 'click', (function(marker,i) {
return function() {
info.setContent(results[i].formatted_address);
info.open(map,marker);
}
})(marker,i));
}
map.fitBounds(latlngbounds);
listener = google.maps.event.addListener(map, "idle", function() {
if (map.getZoom() > 16) map.setZoom(16);
google.maps.event.removeListener(listener);
});
}
} else {
alert("Geocoder failed due to: " + status);
}
});
} else { alert("Wrong lat,lng format!"); } } Reverse Geocoding
Generating Directions
The Google Map API provides a great direction service for calculating routes between two or more addresses. This service can be enabled by initializing google.maps.DirectionsService, which takes no parameters but has one method called route(). This method takes two parameters: an object from google.maps.DirectionsRequest and a callback function.
The basic properties of DirectionRequest are origin, destination, and the travelMode that defines the mode of transportation. DirectionsStatus contains the repsonse status for the directions request.
To expose the resulting routes, there is DirectionsRenderer, which takes no parameters and has a method called setMap for defining the map and a method called setDirections that sets the returned response.
For more details about the directions service, read this tutorial
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 var directionsService = new google.maps.DirectionsService(); var directionsDisplay = new google.maps.DirectionsRenderer();
map = new google.maps.Map(document.getElementById("map-canvas"),mapOptions);
directionsDisplay.setMap(map);
var request = { origin: "Mansoura, Daqahlia, Egypt", destination: "Cairo, Egypt", travelMode: google.maps.DirectionsTravelMode.DRIVING }; directionsService.route(request, function(response, status) { //Check if request is successful. if (status == google.maps.DirectionsStatus.OK) { console.log(status); directionsDisplay.setDirections(response); //Display the directions result } }); Direction between Cairo and Manousoura cities
Map Controls
Google Maps provides controls on the map for handling and manipulating the map UI. These controls can be disabled, moved, or even customized with new functionality.
The available controls are:
Zoom control Pan control Scale control MapType control Streetview control Rotate control Overview map control The default UI controls can be disabled by adding disableDefaultUI: true to the map options.
To remove one of the default controls, add it as an attribute on the MapOptions, like panControl: true, zoomControl: false.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var mapOptions = { center: new google.maps.LatLng(30.055487, 31.279766), zoom: 8, mapTypeId: google.maps.MapTypeId.NORMAL, panControl: true, zoomControlOptions: { style: google.maps.ZoomControlStyle.SMALL, position: google.maps.ControlPosition.LEFT_CENTER }, mapTypeControlOptions: { style: google.maps.MapTypeControlStyle.DROPDOWN_MENU, mapTypeIds: [google.maps.MapTypeId.ROADMAP, "map_style"] }, scaleControl: false, streetViewControl: true, overviewMapControl: true }; Simple and Custom controls (fullscreen,zoom)
Custom Map Styles
This feature give the ability to manipulate the standard base map presentation UI.
Map presentation is composed of two characteristics: Map features lie roads, park, mountains, etc. and Styles for various map elements.
Gotcha: The style array has a limited number of characters allowed which, if exceeded, prevents the style from being applied to the map.
To create a custom map style, do the following:
First: Create the style array with two basic properties MapFeatures and stylers:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 var mapstyle = [ { "featureType": "administrative.locality", "elementType": "labels.icon", "stylers": [ { "invert_lightness": true }, { "color": "#e40952" }, { "visibility": "on" } ] },{ "featureType": "water", "elementType": "geometry.fill", "stylers": [ { "visibility": "on" }, { "hue": "#5eff00" }, { "color": "#282744" }, { "weight": 0.1 }, { "saturation": -56 }, { "lightness": 22 }, { "gamma": 3.91 } ] } ] Second: Set the mapTypeId in the map options:
1 2 3 4 5 6 7 8 9 var mapOptions = { center: new google.maps.LatLng(30.055487, 31.279766), zoom: 8, mapTypeId: google.maps.MapTypeId.NORMAL, mapTypeControlOptions: { style: google.maps.MapTypeControlStyle.DROPDOWN_MENU, mapTypeIds: [google.maps.MapTypeId.ROADMAP, "map_style"] } }; Third: Instantiate the StyledMapType, providing the pre-defined mapstyle array and the map name. The name will appear in the control as a style option.
1 2 var styledMap = new google.maps.StyledMapType(mapstyle, {name: "styled map"}); map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions); Fourth: Add our customized map style to the map’s mapTypes:
1 map.mapTypes.set("map_style", styledMap); Fifth: Set the mapType ID to our styled map:
1 map.setMapTypeId("map_style"); Giving Custom style to the map
Useful Rails Gems
Geocoder
The Geocoder gem provides geocoding, reverse gecoding, finding nearby locations, determining distances, and map services for Ruby.
NOTE: Geocoder supports using rails3 and rails4, there’s another branch for rails2.
Geocoder is installed like any Ruby gem using gem install geocoder or adding gem "geocoder" to the Gemfile and running bundle install.
You have to add two float fields (lat, lng) to any model used to store latitude and longitude values after fetching them by street address or zip codes like so:
1 2 rails generate migration AddLatitudeAndLongitudeToModel lat:float lng:float rake db:migrate Also, add the following to the model to specify which service will be used (geocoder or reverse geocoder):
1 2 3 geocoded_by :address
after_validation :geocode, if: :address_changed? This full_street_address needs to be implemented on the model to create a readable address.
NOTE: Geocoder supports some of the popular databases like (MySQL, PostgreSQL, MongoDB).
The Geocoder also gem provides you with an easy way to swap between various geocoding providers.
GMaps4rails
GMaps4rails is an awesome gem that provides geocoding and map locations. It uses JS to generate filters when rendering markers. It also has a geocoding feature that calculates simple lat, lng values.
You can combine this gem with the Geocoder gem features, rendering the results on the map using GMaps4rails.
Installation
First: Add the following line to your Gemfile file:
1 gem 'gmaps4rails Then run bundle install
Second: Add a div to hold the map:
1 2 3
1 2
<script src="//maps.google.com/maps/api/js?v=3.13&sensor=false&libraries=geometry" type="text/javascript"></script> <script src='//google-maps-utility-library-v3.googlecode.com/svn/tags/markerclustererplus/2.0.14/src/markerclusterer_packed.js' type='text/javascript'></script>Fourth: Require the underscore.js library too, because Gmaps4rails uses it. In your Rails application.js:
1 2 //= require underscore //= require gmaps/google Now, create the map as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 handler = Gmaps.build('Google'); handler.buildMap( { provider: { disableDefaultUI: true // here you can pass other Google Maps API options here }, internal: { id: 'map' } }, function() { markers = handler.addMarkers([ { "lat": 0, "lng": 0, "picture": { "url": "https://addons.cdn.mozilla.net/img/uploads/addon_icons/13/13028-64.png", "width": 36, "height": 36 }, "infowindow": "hello!" } ]); handler.bounds.extendWith(markers); handler.fitMapToBounds(); } ); For more details about this gem, check this link.
Alternatives to Google Maps
Leaflet.js
Leaflet is a modern JavaScript library for embedding maps which gained its popularity from simplicity and ease of implementing markers, overlays, and manipulating various map components. Leaflet can be extended with the enormous set of available plugins. It uses a permissive BSD open-source license, so it can be added to any site without legal issues. Also, it supports multiple map providers, including OpenStreetMap, MapQuestOpen, Stamen, Esri, and OpenWeatherMap.
Installation
Download it from its official site leaflet.com. It is available as a .zip file or a fork on github.
A snip of code to illustrate Leaflet’s simplicity:
1 2 3 4 5 6 7 8 9 10 11 12 // create a map in the "map" div, set the view to a given place and zoom var map = L.map('map').setView([51.505, -0.09], 13);
// add an OpenStreetMap tile layer L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map);
// add a marker in the given location, attach some popup content to it and open the popup
L.marker([51.5, -0.09]).addTo(map)
.bindPopup('A pretty CSS3 popup.
Easily customizable.')
.openPopup();
Check the Leaflet quick start for more information.
MapBox
MapBox is a beautiful tool which gives flexibility for creating maps. It has the ability to design custom maps with wonderful layers and a lot of custom features with TileMill (map design studio), a downloadabale application. Or you can create MapBox web applications with custom markers and overlays by using its JavaScript API.
Installaton
All you need is an account on MapBox. Once you’ve created some maps on MapBox, those Map IDs are used to integrate it with your web application.
This example will give you just a glance about using MapBox with JavaScript.
After creating your map on MapBox, include the Mapbox.js library on your project.
First: Initialize the map:
1 var map = mapbox.map('map'); Second: Set the zoom range and center zoom point of the map:
1 2 3 4 5 6 map.setZoomRange(5, 15);
map.centerzoom({ lat: 37.871385, lon: -99.228516 }, 5); Third: Add the custom layer you created on MapBox.
1 map.addLayer(mapbox.layer().id('YOUR-MAP-ID-HERE')); After that, you can embed more features in the map, like markers, UI features (fullscreen, zoomer) and so on.
NOTE: This is not an in-depth tutorial on how to use MapBox, but it exposes it as an alternative option to Google Maps.
Summary
This tutorial gives a basic understanding of how to create maps and general map concepts. Hopefully, you can now create a map to meet your needs using any map API you choose.