[Rails] Affichage de Google Maps à l'aide de l'API Google Maps et recherche d'itinéraires entre plusieurs points

introduction

Il y a très peu d'articles qui peuvent être utilisés comme référence, et c'était la partie la plus difficile de la création d'un portfolio, alors je l'ai écrit parce que je pensais que ce serait bien de le laisser comme une sortie pour mon propre apprentissage et pour aider quelqu'un! Quelle est la signification de cette description en tant que débutant? J'ai l'intention d'expliquer la partie que je pense. bien sûr! Veuillez noter que je pense qu'il y a plusieurs parties.

Cible

En plus d'afficher Google Map avec l'API Google Maps, vous pouvez l'ajouter arbitrairement à la liste de recherche d'itinéraire à partir de la bulle de repère, et l'objectif est de rechercher des itinéraires à plusieurs points. ezgif com-optimize-2

Environnement de développement

・ Rubis: 2.5.1 ・ Rails: 5.2.1 ・ Système d'exploitation: macOS

supposition

・ Introduction de Slim -Activez les API suivantes sur la plate-forme officielle Google Maps ・ API JavaScript Maps → Affichage de Google Map ・ API de géocodage → Calcul de la latitude et de la longitude à partir de l'adresse ・ API Directions → Recherche d'itinéraire

Réglage

1. Installez les gemmes requises

Gemfile


gem 'dotenv-rails' #Faire de la clé API une variable d'environnement
gem 'gon' #Rendez les variables d'instance définies dans le contrôleur disponibles en JavaScript.
gem 'geocoder' #Calculez la latitude et la longitude à partir de l'adresse.

Terminal


$ bundle install

2. Faites de la clé API une variable d'environnement

Créez un fichier ".env" directement sous l'application

Terminal


$ touch .env 

Écrivez votre propre clé API dans ''

.env


GOOGLE_MAP_API = 'Propre clé API copiée'

.gitignore


/.env

3. Désactivez les turbolinks

Gemfile


gem 'turbolinks' #Supprimer cette ligne

app/assets/javascripts/application.js


//= require turbolinks //Supprimer cette ligne

data-turbolinks-track ': supprimer l'attribut'reload'

ruby:app/views/layouts/application.html.slim


= stylesheet_link_tag    'application', media: 'all'
= javascript_include_tag 'application'

4. Rendre l'API de géocodage disponible

Créer et modifier le fichier de configuration du géocorder

Terminal


$ touch config/initializers/geocoder.rb

config/initializers/geocoder.rb


#Postscript
Geocoder.configure(
  lookup: :google,
  api_key: ENV['GOOGLE_MAP_API']
)

Ceci termine les réglages. De là, nous entrerons dans l'implémentation qui affiche Google Map.

Affichage de Google Map

1. Ajoutez une colonne au modèle que vous souhaitez ajouter

Pour votre propre application, ajoutez une colonne d'adresse à votre modèle Place. Les colonnes de latitude et de longitude sont les valeurs de longitude / latitude calculées à partir des valeurs de la colonne d'adresse par l'API de géocodage. Puisqu'il s'agit d'une valeur fractionnaire, le type utilise float.

Terminal


$ rails g migration AddColumnsToPlaces address:string latitude:float longitude:float

Terminal


$ rails db:migrate

2. Modifiez le modèle

models/place.rb


  #Postscript
  geocoded_by :address #Calculez la latitude et la longitude en fonction de la colonne d'adresse.
  after_validation :geocode #Lors du changement d'adresse, la latitude et la longitude sont également modifiées.

3. Modifiez le contrôleur

controllers/places_controller.rb


def index
  @place = Place.all
  gon.place = @place #Postscript
end

private
  def place_params
    #"Adresse" ajoutée aux paramètres forts
    params.require(:place).permit(:name, :description, :image, :address)
  end

4. Modifier la vue

① Modifiez application.html.slim Écrivez pour charger gon avant CSS et JavaScript.

ruby:views/layouts/application.html.slim


doctype html
html
  head
    title
      | app_name
    = csrf_meta_tags
    = csp_meta_tag
    = include_gon #Postscript
    = stylesheet_link_tag    'application', media: 'all'
    = javascript_include_tag 'application'

② Ajouter un formulaire de saisie d'adresse au nouvel écran d'inscription

ruby:views/places/new.html.slim


= f.label :address, 'adresse de rue'
= f.text_field :address, class: 'form-control'

③ Décrivez dans le fichier qui affiche Google Map

ruby:views/places/index.html.slim


div id = 'map_index' #Donnez votre identifiant,Google Map décrit dans le fichier js est intégré dans cette partie
- google_api = "https://maps.googleapis.com/maps/api/js?key=#{ ENV['GOOGLE_MAP_API'] }&callback=initMap".html_safe
script{ async src = google_api }

.map-route
  <Liste de recherche d'itinéraire>
  ul id = "route-list" class = "list-group" #Le bouton d'ajout dans la bulle du fichier js ajoute cet emplacement à l'élément li


div id = 'directions-panel' #La distance / le temps est intégré
  <Distance / temps entre les points>
  ul id = "display-list" class = "display-group"

.map-search
   = button_tag "Recherche d'itinéraire", id: "btn-search", class: "btn btn-primary", onclick:     "search()" #Recherche par traitement des clics()Appeler une fonction

[À propos de google_api = ~ ~ ~ ~] → Appelez la fonction initMap lors de la lecture dans le processus de rappel. → .html_safe est un traitement d'échappement → L'attribut async charge JavaScript de manière asynchrone pour accélérer le rendu.

④ Décrivez la taille que vous souhaitez afficher sur Google Map en scss

stylesheets/application.scss


#map_index{
  height: 400px;
  width: 400px; 
}

5. Modifier le fichier JavaScript

Ceci est le cœur. Créez un nouveau fichier directement sous assets / javascripts et décrivez-le. Cela peut être difficile à voir pendant longtemps, mais après avoir défini les variables, nous définissons simplement chaque fonction. la fonction est, ・ InitMap ・ MarkerEvent (i) ・ AddPlace (nom, lat, lng, numéro) · Chercher () Il y en a quatre dans l'ordre de. Veuillez vous référer au commentaire pour les parties et les points difficiles à comprendre.

assets/javascripts/googlemap.js


var map
var geocoder
var marker = [];
var infoWindow = [];
var markerData = gon.places; //Assignez la variable d'instance définie par le contrôleur à la variable
var place_name = [];
var place_lat = [];
var place_lng = [];

//Fonction pour afficher GoogleMap(Appelé en traitement de rappel)
function initMap(){
    geocoder = new google.maps.Geocoder()
    //Afficher l'identifiant='map_index'Intégrer Google Map dans la partie de
    map = new google.maps.Map(document.getElementById('map_index'), {
      center: { lat: 35.6585, lng: 139.7486 }, //Centrage sur la tour de Tokyo
      zoom: 9,
    });

    //Afficher plusieurs marqueurs et bulles par traitement itératif
    for (var i = 0; i < markerData.length; i++) {
      //Calculez la latitude et la longitude de chaque point
      markerLatLng = new google.maps.LatLng({
        lat: markerData[i]['latitude'],
        lng: markerData[i]['longitude']
      });
      
      //Affichage des marqueurs
      marker[i] = new google.maps.Marker({
        position: markerLatLng,
        map: map
      });

      //Affichage du ballon
      let id = markerData[i]['id']
      place_name[i]= markerData[i]['name'];
      place_lat[i]= markerData[i]['latitude'];
      place_lng[i]= markerData[i]['longitude'];
      infoWindow[i] = new google.maps.InfoWindow({
        //Contenu du ballon,Passez le tableau et le numéro de tableau de chaque attribut comme arguments
        content: `<a href='/places/${ id }'>${ markerData[i]['name'] }</a><input type="button" value="ajouter à" onclick="addPlace(place_name, place_lat, place_lng, ${i})">`
      });
      markerEvent(i);
    }
  }
}

//Cliquez sur le marqueur pour afficher une bulle
function markerEvent(i) {
  marker[i].addListener('click', function () {
    infoWindow[i].open(map, marker[i]);
  });
}

//Ajouter à la liste
function addPlace(name, lat, lng, number){
  var li = $('<li>', {
    text: name[number],
    "class": "list-group-item"
  });
  li.attr("data-lat", lat[number]); // data-lat à l'attribut lat[number]Mettre en
  li.attr("data-lng", lng[number]); // data-lng à l'attribut lng[number]Mettre en
  $('#route-list').append(li); //id est la route-Ajouter li à la fin de l'élément de liste
}

//Rechercher un itinéraire
function search() {
  var points = $('#route-list li');

  //Lorsqu'il y a deux points ou plus
  if (points.length >= 2){
      var origin; //Point de départ
      var destination; //Point final
      var waypoints = []; //Waypoint

      // origin, destination,Définir des waypoints
      for (var i = 0; i < points.length; i++) {
          points[i] = new google.maps.LatLng($(points[i]).attr("data-lat"), $(points[i]).attr("data-lng"));
          if (i == 0){
            origin = points[i];
          } else if (i == points.length-1){
            destination = points[i];
          } else {
            waypoints.push({ location: points[i], stopover: true });
          }
      }
      //Faire une demande
      var request = {
        origin:      origin,
        destination: destination,
        waypoints: waypoints,
        travelMode:  google.maps.TravelMode.DRIVING
      };
      //Demande de service racine
      new google.maps.DirectionsService().route(request, function(response, status) {
        if (status == google.maps.DirectionsStatus.OK) {
          new google.maps.DirectionsRenderer({
            map: map,
            suppressMarkers : true,
            polylineOptions: { //Paramètres des lignes dessinées
              strokeColor: '#00ffdd',
              strokeOpacity: 1,
              strokeWeight: 5
            }
          }).setDirections(response);//Partie de dessin de ligne
          
            //Afficher la distance et le temps
            var data = response.routes[0].legs;
            for (var i = 0; i < data.length; i++) {
                //distance
                var li = $('<li>', {
                  text: data[i].distance.text,
                  "class": "display-group-item"
                });
                $('#display-list').append(li);

                //temps
                var li = $('<li>', {
                  text: data[i].duration.text,
                  "class": "display-group-item"
                });
                $('#display-list').append(li);
            }
            const route = response.routes[0];
            //Afficher l'identifiant='directions-panel'Incorporer dans la partie de
            const summaryPanel = document.getElementById("directions-panel");
            summaryPanel.innerHTML = "";

            //Afficher la distance et le temps entre chaque point
            for (let i = 0; i < route.legs.length; i++) {
              const routeSegment = i + 1;
              summaryPanel.innerHTML +=
                "<b>Route Segment: " + routeSegment + "</b><br>";
              summaryPanel.innerHTML += route.legs[i].start_address + "<br>" + " ↓ " + "<br>";
              summaryPanel.innerHTML += route.legs[i].end_address + "<br>";
              summaryPanel.innerHTML += "<" + route.legs[i].distance.text + ",";
              summaryPanel.innerHTML += route.legs[i].duration.text + ">" + "<br>";
            }
        }
      });
  }
}



__ Supplément à la partie contenu du contenu de la bulle: (car j'ai eu du mal avec la méthode de transmission des données) __

content: `<a href='/places/${ id }'>${ markerData[i]['name'] }</a><input type="button" value="ajouter à" onclick="addPlace(place_name, place_lat, place_lng, ${i})">`

addPlace(place_name, place_lat, place_lng, ${i}) Dans l'appel à cette fonction, les trois arguments précédents sont passés sous forme de tableau. Le quatrième argument est l'expansion de l'expression du nombre (appelé index) qui représente les informations du tableau. L'expansion d'expression en JavaScript semble être cette forme. En fournissant un tel argument, la fonction addPlace (nom, lat, lng, nombre) peut traiter des informations sur les données dont il s'agit normalement.

finalement

Merci d'avoir lu jusqu'au bout. Je suis moi-même dans un état où le portefeuille est en voie d'achèvement et j'ai commencé une recherche d'emploi à grande échelle! Nous soutenons sincèrement ceux qui ont des objectifs, comme créer des portefeuilles et changer d'emploi, alors faisons de notre mieux ensemble! !!

référence

Recommended Posts

[Rails] Affichage de Google Maps à l'aide de l'API Google Maps et recherche d'itinéraires entre plusieurs points
Afficher l'API Google Maps avec Rails et affichage des broches
[Google Maps API] La carte n'est pas affichée et devient vide [Rails]
[Ruby on Rails] Affichage et épinglage de GoolgeMAP à l'aide de l'API Google
[Rails] google maps api Comment publier et afficher des informations cartographiques
[Rails] Description de l'API Google Maps lorsque la latitude et la longitude ne peuvent pas être enregistrées
[Rails 6 / API Google Map] Publiez une adresse et définissez plusieurs marqueurs sur la carte
Enregistrement facile des livres avec l'API et Rails de Google Livres
Procédure de transcription vocale à l'aide de Python et de l'API Google Cloud Speech
[Ruby on Rails] Google map plusieurs broches, bulles, liens
Les débutants de l'API Google Maps et de l'API Twitter ont créé "Tweet Map"
[Affichage de la carte] Affichez une carte à partir de l'adresse enregistrée par l'utilisateur à l'aide de l'API JavaScript de Google Maps et de l'API de géocodage!
J'ai essayé d'utiliser l'API de reconnaissance vocale docomo et l'API Google Speech en Java