[Java] Display Google Maps API with Rails / Pin display

2 minute read

Introduction

I used Google Maps API in my portfolio in the past, but I was reminded because I forgot the flow.

environment

rails 5.2.3 ruby 2.6.3

What to do this time

  • Get the longitude and latitude from the current location information and display the marker.
  • The acquired list information is converted to json format and placed as a marker on the map. ・Display of map

spaces_controller.rb


  def search
    @spaces = Space.all
  end

Create a model, enter the address, and automatically obtain the latitude and longitude.

space.rb


class Space <ApplicationRecord
  geocoded_by :address
  after_validation :geocode, if: :address_changed?
end

schema.rb


create_table "spaces", force: :cascade do |t|
    t.string "address"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.float "latitude"
    t.float "longitude"
end

Display MAP script

javascript


  function initMap()
    // Where to display the map
    var target = document.getElementById('gmap');
    //Map display
    var map = new google.maps.Map(document.getElementById('gmap'), (
      center: {lat: 35.681167, lng: 139.767052}, //center point setting
      zoom: 8//map magnification setting
    });

    // Create a location marker
    //If you cannot get your current location
    if(!navigator.geolocation){
      infoWindow.setPosition(map.getCenter());
      infoWindow.setContent('Geolocation is not supported');
      infoWindow.open(map);
    }

    navigator.geolocation.getCurrentPosition(function(position) {
      // Get the latitude of the current location
      var pos = {lat: position.coords.latitude, lng: position.coords.longitude };
      var mark = new google.maps.Marker({
        // Dropdown animation settings
        animation: google.maps.Animation.DROP,
        position: pos,
        map: map,
        // Create a pin for your current location. This time, the default design is used for multiple markers, so changed.
        icon: {
          fillColor: "rgb(48, 255, 176)",
          fillOpacity: 1.0,
          path: google.maps.SymbolPath.BACKWARD_CLOSED_ARROW,
          scale: 4,
          strokeColor: "green",
          strokeWeight: 1.0
        }
      });
    }, function() {
      infoWindow.setPosition(map.getCenter());
      infoWindow.setContent('Error: Geolocation is invalid.');
      infoWindow.open(map);
    });
    // multiple markers
    // list data in json format
    var spaces = #{raw @spaces.to_json};
    var marker = [];
    var info;
    for(var i = 0; i <spaces.length; ++i) {
      //Create a marker by extracting the longitude and latitude information one by one from the list
      spot = new google.maps.LatLng({lat: spaces[i].latitude, lng: spaces[i].longitude});
      marker[i] = new google.maps.Marker({
        position: spot,
        map: map,
      animation: google.maps.Animation.DROP
      });
      markerEvent(i);
    }
    //Multi-marker hover event
    function markerEvent(i) {
      marker[i].addListener('mouseover', function() {
        var target = $('#' + (i + 1));
        $(".highlight").removeClass("highlight");
        target.addClass("highlight");
        var position = target.offset().top-280;
        $('body,html').animate({scrollTop:position}, 400,'swing');
      });
    }
    //------------------------------------------------ -------------
  }


script src="https://maps.googleapis.com/maps/api/js?key=#{ENV[""]}&callback=initMap" async defer

Note that this time the template engine is slim and written directly in it, so the storage of data variables is different from usual. It is very easy to get the longitude and latitude from the name when you use the gem’s geocoder, but since it is not accurate and it does not display even the address unit, I am using Google Geocoding this time.