Zoeken…


Voeg de javascript-tag van Google maps toe aan de layoutkop

Om Google Maps goed te laten werken met turbolinks , voegt u de JavaScript-tag rechtstreeks toe aan de lay- outkop in plaats van deze op te nemen in een weergave.

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

De google_maps_api_script_tag kan het beste in een helper worden gedefinieerd.

# 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

U kunt uw toepassing registreren bij Google en uw API-sleutel ophalen in de Google API-console . Google heeft een korte handleiding voor het aanvragen van een API-sleutel voor de JavaScript-API van Google Maps .

De api-sleutel wordt opgeslagen in het bestand secrets.yml :

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

Vergeet niet om config/secrets.yml .gitignore toe te voegen aan uw .gitignore bestand en zorg ervoor dat u de api-sleutel niet in de repository vastlegt.

Geocode het model

Stel dat uw gebruikers en / of groepen profielen hebben en dat u adresprofielvelden op een google map wilt weergeven.

# 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

Een geweldige manier om de adressen te geocoderen, dwz longitude en latitude is de geocoder-parel .

Voeg geocoder toe aan uw Gemfile en voer de bundle uit om deze te installeren.

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

Voeg databasekolommen voor latitude en longitude toe om de locatie in de database op te slaan. Dit is efficiënter dan elke keer dat u de locatie nodig hebt, vragen naar de geocoderingsservice. Het is sneller en u bereikt de vraaglimiet niet zo snel.

➜ 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

Voeg het geocodeermechanisme toe aan uw model. In dit voorbeeld wordt de adresstring opgeslagen in het value . Configureer de geocodering om uit te voeren wanneer het record is gewijzigd en alleen wanneer een waarde aanwezig is:

# 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

Standaard gebruikt geocoder Google als opzoekservice. Het heeft veel interessante functies zoals afstandsberekeningen of nabijheid zoeken. Kijk voor meer informatie op de geocoder README .

Toon adressen op een google map in de profielweergave

Geef in de profielweergave de profielvelden van een gebruiker of groep in een lijst weer, evenals de adresvelden op een google map.

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

De juiste @profile_fields en @address_fields worden ingesteld in de controller:

# 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

Initialiseer de kaart, plaats de markeringen, stel de zoom en andere kaartinstellingen in met javascript.

Voorbeeld van profielweergave

Plaats de markeringen op de kaart met JavaScript

Stel dat er een .google_map div is, die de kaart wordt en die de adresvelden heeft om als markeringen als data worden weergegeven.

Bijvoorbeeld:

<!-- 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>

Gebruik de jquery.turbolinks-edelsteen om gebruik te maken van het $(document).ready evenement met turbolinks zonder de turbolinks-gebeurtenissen handmatig te beheren.

Als u later nog andere bewerkingen met de kaart wilt uitvoeren, bijvoorbeeld filteren of informatievensters, is het handig om de kaart te laten beheren door een koffiescriptklasse .

# 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

Wanneer u meerdere koffie-scriptbestanden gebruikt, die standaard een naamruimte hebben, is het handig om een algemene App naamruimte te definiëren die wordt gedeeld door alle koffie-scriptbestanden.

Loop vervolgens (mogelijk meerdere) .google_map divs door en maak voor elk een exemplaar van de klasse App.GoogleMap .

# 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

Initialiseer de kaart met een koffiescriptklasse.

Mits een App.GoogleMap koffie- App.GoogleMap , kan de google map als volgt worden geïnitialiseerd:

# 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
  }

Voor meer informatie over de mogelijk te leren map_configuration opties, eens een kijkje op google MapOptions documentatie en hun gids voor het toevoegen van bedieningselementen .

Ter referentie wordt de klasse google.maps.Map hier uitgebreid gedocumenteerd .

Initialiseer de kaartmarkeringen met behulp van een koffiescriptklasse

Op voorwaarde dat een App.GoogleMap koffie- App.GoogleMap en de markeringsinformatie wordt opgeslagen in het kenmerk data-address-fields van de .google_map div, kunnen de .google_map als volgt op de kaart worden geïnitialiseerd:

# 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

Raadpleeg de documentatie van MarkerOptions van Google en hun gids voor markeringen voor meer informatie over opties voor markeringen .

Zoom automatisch op een kaart met een koffiescriptklasse

Mits een App.GoogleMap koffie- App.GoogleMap met de google.maps.Map opgeslagen als @map en de google.maps.Marker opgeslagen als @markers , kan op de kaart automatisch worden ingezoomd, dwz aangepast dat alle markers zichtbaar zijn, zoals deze : op de kaart als volgt:

# 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

Bekijk de LatLngBounds-documentatie van Google voor meer informatie over grenzen.

De modeleigenschappen blootstellen als json

Om adresprofielvelden weer te geven als markeringen op een google map, moeten de adresveldobjecten als json-objecten worden doorgegeven aan javascript.

Reguliere database-attributen

Wanneer u to_json op een ApplicationRecord object, worden de database-kenmerken automatisch weergegeven.

Gegeven een ProfileFields::Address met kenmerken voor label , value , longitude en latitude , resulteert address_field.as_json in een Hash , bijvoorbeeld representatie,

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

die wordt omgezet in een json-string door to_json :

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

Dit is handig omdat het mogelijk is om label en value later in javascript te gebruiken, bijvoorbeeld om tooltips voor de kaartmarkeringen weer te geven.

Overige attributen

Andere virtuele kenmerken kunnen worden weergegeven door de as_json methode te overschrijven.

Bijvoorbeeld, om een bloot title attribuut, opnemen in het samengevoegde as_json hash:

# 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

In het bovenstaande voorbeeld wordt super gebruikt om de oorspronkelijke methode as_json aan te roepen, die de oorspronkelijke attribuuthash van het object retourneert en deze samenvoegt met de vereiste positiehash.

Bekijk het blogbericht van jjulian om het verschil tussen as_json en to_json te begrijpen.

Positie

Om markeringen weer te geven, vereist de API van Google Maps standaard een position hash waarin lengte- en breedtegraad is opgeslagen als respectievelijk lng en lat .

Deze positie-hash kan worden gemaakt in javascript, later of hier bij het definiëren van de json-weergave van het adresveld:

Om deze position als json-kenmerk van het adresveld op te geven, overschrijft u gewoon de as_json methode op het model.

# 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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow