Suche…


Fügen Sie den Javascript-Tag von Google Maps zum Layout-Header hinzu

Damit Google Maps ordnungsgemäß mit Turbolinks funktioniert, fügen Sie das Javascript-Tag direkt zum Layout-Header hinzu, anstatt es in eine Ansicht aufzunehmen.

# app/views/layouts/my_layout.html.haml
!!!
%html{:lang => 'en'}
  %head
    - # ...
    = google_maps_api_script_tag

Der google_maps_api_script_tag sich am besten in einem Helfer definieren.

# app/helpers/google_maps_helper.rb
module GoogleMapsHelper
  def google_maps_api_script_tag
    javascript_include_tag google_maps_api_source
  end

  def google_maps_api_source
    "https://maps.googleapis.com/maps/api/js?key=#{google_maps_api_key}"
  end

  def google_maps_api_key
    Rails.application.secrets.google_maps_api_key
  end
end

Sie können Ihre Anwendung bei Google registrieren und Ihren API-Schlüssel in der Google API-Konsole abrufen . Google hat eine kurze Anleitung, wie Sie einen API-Schlüssel für die Google Maps-JavaScript-API anfordern .

Der API-Schlüssel wird in der Datei secrets.yml gespeichert:

# config/secrets.yml
development:
  google_maps_api_key: '...'
  # ...
production:
  google_maps_api_key: '...'
  # ...

Vergessen Sie nicht, config/secrets.yml zu Ihrer .gitignore Datei .gitignore und sicherzustellen, dass Sie den API-Schlüssel nicht in das Repository einbinden.

Geokodieren Sie das Modell

Angenommen, Ihre Benutzer und / oder Gruppen verfügen über Profile, und Sie möchten Adressprofilfelder auf einer Google-Map anzeigen.

# app/models/profile_fields/address.rb
class ProfileFields::Address < ProfileFields::Base
  # Attributes: 
  # label, e.g. "Work address"
  # value, e.g. "Willy-Brandt-Straße 1\n10557 Berlin"
end

Eine gute Möglichkeit, die Adressen zu geokodieren, dh longitude und latitude anzugeben, ist der Geocoder-Edelstein .

Fügen Sie Geocoder zu Ihrem Gemfile und führen Sie ein bundle , um es zu installieren.

# Gemfile
gem 'geocoder', '~> 1.3'

Fügen Sie Datenbankspalten für latitude und longitude , um den Standort in der Datenbank zu speichern. Dies ist effizienter, als den Geokodierungsdienst jedes Mal abzufragen, wenn Sie den Standort benötigen. Es ist schneller und Sie erreichen das Abfragelimit nicht so schnell.

➜ bin/rails generate migration add_latitude_and_longitude_to_profile_fields \
    latitude:float longitude:float
➜ bin/rails db:migrate  # Rails 5, or:
➜ rake db:migrate       # Rails 3, 4

Fügen Sie Ihrem Modell den Geokodierungsmechanismus hinzu. In diesem Beispiel wird die Adresszeichenfolge im value Attribut gespeichert. Konfigurieren Sie die Geokodierung so, dass sie ausgeführt wird, wenn sich der Datensatz geändert hat und nur ein Wert vorhanden ist:

# app/models/profile_fields/address.rb
class ProfileFields::Address < ProfileFields::Base
  geocoded_by :value
  after_validation :geocode, if: ->(address_field){ 
    address_field.value.present? and address_field.value_changed? 
  }

end

Geocoder verwendet standardmäßig Google als Suchdienst. Es hat viele interessante Features wie Entfernungsberechnungen oder Annäherungssuche. Weitere Informationen finden Sie in der README des Geocoders .

Zeigen Sie Adressen auf einer Google-Karte in der Profilansicht an

Zeigen Sie in der Profilansicht die Profilfelder eines Benutzers oder einer Gruppe in einer Liste sowie die Adressfelder in einer Google-Map an.

- # app/views/profiles/show.html.haml
%h1 Contact Information
.profile_fields
  = render @profile_fields
.google_map{data: address_fields: @address_fields.to_json }

Die entsprechenden @profile_fields und @address_fields werden im Controller festgelegt:

# app/controllers/profiles_controller.rb
class ProfilesController < ApplicationController
  def show
    # ...
    @profile_fields = @user_or_group.profile_fields
    @address_fields = @profile_fields.where(type: 'ProfileFields::Address')
  end
end

Initialisieren Sie die Karte, setzen Sie die Markierungen, stellen Sie den Zoom und andere Karteneinstellungen mit Javascript ein.

Beispielprofilansicht

Setzen Sie die Markierungen auf der Karte mit Javascript

Nehmen wir an , es gibt eine .google_map div, die die Karte mit sich, und die hat die Adressfelder als Marker zu zeigen , data

Zum Beispiel:

<!-- http://localhost:3000/profiles/123 -->
<div class="google_map" data-address-fields="[
  {label: 'Work address', value: 'Willy-Brandt-Straße 1\n10557 Berlin', 
  position: {lng: ..., lat: ...}},
  ...
]"></div>

Um das $(document).ready mit Turbolinks zu nutzen, ohne die Turbolinks-Ereignisse von Hand zu verwalten, verwenden Sie den Edelstein jquery.turbolinks .

Wenn Sie später noch andere Vorgänge mit der Karte ausführen möchten, z. B. Filter- oder Infofenster, ist es sinnvoll, die Karte von einer Kaffeeskriptklasse verwalten zu lassen.

# app/assets/javascripts/google_maps.js.coffee
window.App = {} unless App?
class App.GoogleMap
  constructor: (map_div)->
    # TODO: initialize the map
    # TODO: set the markers

Wenn Sie mehrere Kaffeeskriptdateien verwenden, die standardmäßig einen Namensraum haben, ist es zweckmäßig, einen globalen App Namensraum zu definieren, der von allen Kaffeeskriptdateien gemeinsam genutzt wird.

Dann durchlaufen Sie (möglicherweise mehrere) .google_map und erstellen App.GoogleMap für jede einzelne eine Instanz der App.GoogleMap Klasse.

# app/assets/javascripts/google_maps.js.coffee
# ...
$(document).ready ->
  App.google_maps = []
  $('.google_map').each ->
    map_div = $(this)
    map = new App.GoogleMap map_div
    App.google_maps.push map

Initialisieren Sie die Karte mit einer Kaffeeskriptklasse.

Eine bereitgestellt App.GoogleMap Kaffee Script - Klasse kann die Google - Karte wie folgt initialisiert werden:

# app/assets/javascripts/google_maps.js.coffee
# ...
class App.GoogleMap
  map_div: {}
  map: {}
  
  constructor: (map_div)->
    @map_div = map_div
    @init_map()
    @reference_the_map_as_data_attribute

  # To access the GoogleMap object or the map object itself
  # later via the DOM, for example 
  # 
  #     $('.google_map').data('GoogleMap')
  #
  # store references as data attribute of the map_div.
  #
  reference_the_map_as_data_attribute: ->
    @map_div.data 'GoogleMap', this
    @map_div.data 'map', @map

  init_map: ->
    @map = new google.maps.Map(@dom_element, @map_configuration) if google?

  # `@map_div` is the jquery object. But google maps needs
  # the real DOM element.
  #
  dom_element: ->
    @map_div.get(0)

  map_configuration: -> {
    scrollWheel: true
  }

Weitere map_configuration zu den möglichen Optionen für map_configuration finden Sie in der Google MapOptions-Dokumentation und in deren Anleitung zum Hinzufügen von Steuerelementen .

Als Referenz ist die Klasse google.maps.Map hier ausführlich dokumentiert .

Initialisieren Sie die Kartenmarkierungen mithilfe einer Kaffeeskriptklasse

GEWäHR App.GoogleMap Kaffee Skript - data-address-fields .google_map Klasse und die Markierungsinformation in dem gespeichert werden data-address-fields Attribut des .google_map div können die Kartenmarkierungen auf der Karte wie folgt initialisiert werden:

# app/assets/javascripts/google_maps.js.coffee
# ...
class App.GoogleMap
  # ...
  markers: []

  constructor: (map_div)->
    # ...
    @init_markers()

  address_fields: ->
    @map_div.data('address-fields')

  init_markers: ->
    self = this  # to reference the instance as `self` when `this` is redefined.
    self.markers = []
    for address_field in self.address_fields()
      marker = new google.maps.Marker {
        map: self.map,
        position: {
          lng: address_field.longitude,
          lat: address_field.latitude
        },
        # # or, if `position` is defined in `ProfileFields::Address#as_json`:
        # position: address_field.position,
        title: address_field.value
      }
      self.markers.push marker

Weitere Informationen zu Markierungsoptionen finden Sie in der Google MarkerOptions-Dokumentation und in deren Leitfaden zu Markern .

Auto-Zoom einer Karte mit einer Kaffeeskriptklasse

Eine bereitgestellt App.GoogleMap Kaffee Skript - google.maps.Map @map google.maps.Marker @markers Klasse mit dem google.maps.Map als gespeicherte @map und die google.maps.Marker s als gespeicherte @markers , die Karte kann automatisch gezoomt, dh eingestellt sein , dass alle Markierungen sichtbar sind, wie dies : auf der Karte wie folgt:

# app/assets/javascripts/google_maps.js.coffee
# ...
class App.GoogleMap
  # ...
  bounds: {}

  constructor: (map_div)->
    # ...
    @auto_zoom()

  auto_zoom: ->
    @init_bounds()
    # TODO: Maybe, adjust the zoom to have a maximum or 
    # minimum zoom level, here.

  init_bounds: ->
    @bounds = new google.maps.LatLngBounds()
    for marker in @markers
      @bounds.extend marker.position
    @map.fitBounds @bounds

Weitere Informationen zu Grenzen finden Sie in der LatLngBounds-Dokumentation von Google .

Darstellen der Modelleigenschaften als Json

Um Adressprofilfelder als Markierungen auf einer Google-Map anzuzeigen, müssen die Adressfeldobjekte als Json-Objekte an Javascript übergeben werden.

Regelmäßige Datenbankattribute

Beim Aufruf von to_json für ein ApplicationRecord Objekt werden die Datenbankattribute automatisch to_json .

Wenn ein ProfileFields::Address Modell mit Attributen für label , value , longitude und latitude , führt address_field.as_json zu einem Hash , z.

address_field.as_json  # =>
  {label: "Work address", value: "Willy-Brandt-Straße 1\n10557 Berlin",
    longitude: ..., latitude: ...}

welches von to_json in einen json-String to_json :

address_field.to_json  # =>
  "{\"label\":\"Work address\",\"value\":\"Willy-Brandt-Straße 1\\n
    10557 Berlin\",\"longitude\":...,\"latitude\":...}"

Dies ist nützlich, da Sie später in Javascript label und value , um beispielsweise Tooltipps für die Kartenmarkierungen anzuzeigen.

Andere Attribute

Andere virtuelle Attribute können durch Überschreiben der as_json Methode as_json werden.

Um beispielsweise ein title Attribut as_json zu machen, as_json es in den zusammengeführten as_json Hash ein:

# app/models/profile_fields/address.rb
class ProfileFields::Address < ProfileFields::Base
  # ...

  # For example: "John Doe, Work address"
  def title
    "#{self.parent.name}, #{self.label}"
  end

  def as_json
    super.merge {
      title: self.title
    }
  end
end

Das obige Beispiel verwendet super , um die ursprüngliche as_json Methode as_json , die den ursprünglichen Attributhash des Objekts zurückgibt und ihn mit dem erforderlichen Positionshash zusammenführt.

Um den Unterschied zwischen as_json und to_json zu verstehen, as_json to_json einen Blick auf diesen Blogbeitrag von jjulian .

Position

Um Marker zu rendern, erfordert die Google Maps-API standardmäßig einen position der Längen- und Breitengrad als lng bzw. lat .

Dieser Positionshash kann in Javascript erstellt werden, später oder hier, wenn Sie die Json-Darstellung des Adressfelds definieren:

Um diese position als json-Attribut des Adressfelds as_json , überschreiben as_json einfach die as_json Methode im Modell.

# app/models/profile_fields/address.rb
class ProfileFields::Address < ProfileFields::Base
  # ...

  def as_json
    super.merge {
      # ...
      position: {
        lng: self.longitude,
        lat: self.latitude
      }
    }
  end
end


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow