I would have user location on my map with stores around him (store model).
I used Google Documentation but I'm lost...
Actually, I have my map with stores, and the map move to the user location but doesn't show the infoWindow "Location found".
Here is my map.js :
import GMaps from 'gmaps/gmaps.js';
import { autocomplete } from '../components/autocomplete';
const mapElement = document.getElementById('map');
if (mapElement) { // don't try to build a map if there's no div#map to inject in
const map = new GMaps({ el: '#map', lat: 0, lng: 0 });
const markers = JSON.parse(mapElement.dataset.markers);
map.addMarkers(markers);
if (markers.length === 0) {
map.setZoom(2);
} else if (markers.length === 1) {
map.setCenter(markers[0].lat, markers[0].lng);
map.setZoom(14);
} else {
map.fitLatLngBounds(markers);
}
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
var infoWindow = new google.maps.InfoWindow({map: map});
infoWindow.setPosition(pos);
infoWindow.setContent('Location found.');
map.setCenter(pos);
}, function() {
handleLocationError(true, infoWindow, map.getCenter());
});
} else {
// Browser doesn't support Geolocation
handleLocationError(false, infoWindow, map.getCenter());
}
function handleLocationError(browserHasGeolocation, infoWindow, pos) {
infoWindow.setPosition(pos);
infoWindow.setContent(browserHasGeolocation ?
'Error: The Geolocation service failed.' :
'Error: Your browser doesn\'t support geolocation.');
}
}
The controller :
class PagesController < ApplicationController
skip_before_action :authenticate_user!
def home
#store_all = Store.all
#stores = Store.where.not(latitude: nil, longitude: nil)
#markers = #stores.map do |store|
{
lat: store.latitude,
lng: store.longitude,
infoWindow: { content: '' + store.name + '<br/>' +
store.category +
'<br>' +
store.address
}
}
end
end
end
And the view:
<div class="wrapper-map text-center">
<div class="container">
<div class="row">
<div class="col-xs-12">
<div
id="map"
style="width: 100%;
height: 600px;"
data-markers="<%= #markers.to_json %>"
></div>
</div>
</div>
</div>
</div>
Thank you for your help, I try a lot of tutorials but lost, I am. :)
Related
I have a map inside a div with a reference #mapa
When i want to trace a route in the map the map refreshes. I want to not refresh the map i have the following code:
<div style="height: 500px; width: auto;" #mapa>
<google-map height="500px" width="100%" [zoom]="zoom" [center]="center" [options]="options" (mapClick)="click($event)">
<map-marker #markerElem *ngFor="let marker of markers" [position]="marker.position" [label]="marker.label" [title]="marker.title" [options]="marker.options" (mapClick)="openInfo(markerElem, marker.info)" (mapDragend)="moveMap($event)">
</map-marker>
<map-info-window>{{ infoContent }}</map-info-window>
</google-map>
</div>
If i remove the div with the reference #mapa and i put it the reference into the <google-map> tag i got the title error and show the map without routes.
trazarRutaMapa() {
const directionsService = new google.maps.DirectionsService;
const directionsDisplay = new google.maps.DirectionsRenderer;
const map = new google.maps.Map(this.mapa.nativeElement, {
zoom: 7,
center: {
lat: this.markers[0].position.lat,
lng: this.markers[0].position.lng
}
});
directionsDisplay.setMap(map);
directionsDisplay.setOptions({
suppressMarkers: false,
draggable: true,
markerOptions: {
icon: 'https://developers.google.com/maps/documentation/javascript/examples/full/images/beachflag.png'
}
});
directionsService.route({
origin: {
lat: this.markers[0].position.lat,
lng: this.markers[0].position.lng
},
destination: {
lat: this.markers[1].position.lat,
lng: this.markers[1].position.lng
},
travelMode: google.maps.TravelMode.DRIVING,
}, (response, status) => {
if (status === google.maps.DirectionsStatus.OK) {
console.log('ESTATUS OKEY');
directionsDisplay.setDirections(response);
} else {
window.alert("Fallo el estatus" + status);
}
});
}
As far as I can see you can accomplish your goal just using the #angular/google-maps official module.
Your HTML will become something like this
<google-map [options]="options">
<map-marker *ngFor="let some of somearray" [icon]="...", [label]="...", [position]="..."></map-marker>
<map-directions-renderer [directions]="..." [options]="..."></map-directions-renderer>
</google-map>
and your trazarRoutaMapa() method will become something like this:
trazarRoutaMapa(): void {
const directionsService = new google.maps.DirectionsService; // better if injected from constructor
const request: google.maps.DirectionsRequest = {
destination: {
lat: this.markers[0].position.lat,
lng: this.markers[0].position.lng
},
origin: {
lat: this.markers[1].position.lat,
lng: this.markers[1].position.lng
},
travelMode: google.maps.TravelMode.DRIVING
};
return directionsService.route(
request,
(response, status) => {
if (status === google.maps.DirectionsStatus.OK) {
console.log('ESTATUS OKEY');
directionsDisplay.setDirections(response);
} else {
window.alert("Fallo el estatus" + status);
}
});
}
Disclaimer: I didn't test the code, just created on notepad copy/pasting :)
I am using vue-google-maps, and I have implemented the plugin and it works flawlessly, but there is a small problem ( or maybe I am not able to do it correctly ). When I implemented the autocomplete functionality it works one way. I enter the address and the map points me to the selected place but when I drag the pointer it doesn't update the address in the search field.
I am using Vuejs 2
and vue-google-maps
This is what I am doing:
<template>
<div>
<label>
AutoComplete
<GmapAutocomplete :position.sync="markers[0].position" #keyup.enter="usePlace" #place_changed="setPlace">
</GmapAutocomplete>
<button #click="usePlace">Add</button>
</label>
<br/>
<gmap-map
:center="center"
:zoom="7"
map-type-id="terrain"
style="width: 100%; height: 500px"
>
<gmap-marker
#dragend="updateMaker"
:key="index"
v-for="(m, index) in markers"
:position="m.position"
:clickable="true"
:draggable="true"
#click="center=m.position"
></gmap-marker>
</gmap-map>
</div>
</template>
<script>
export default {
data() {
return {
center: {lat: 10.0, lng: 10.0},
markers: [{
position: {lat: 11.0, lng: 11.0}
}],
place: null,
}
},
description: 'Autocomplete Example (#164)',
methods: {
setPlace(place) {
this.place = place
},
setDescription(description) {
this.description = description;
},
usePlace(place) {
if (this.place) {
var newPostion = {
lat: this.place.geometry.location.lat(),
lng: this.place.geometry.location.lng(),
};
this.center = newPostion;
this.markers[0].position = newPostion;
this.place = null;
}
},
updateMaker: function(event) {
console.log('updateMaker, ', event.latLng.lat());
this.markers[0].position = {
lat: event.latLng.lat(),
lng: event.latLng.lng(),
}
},
}
}
</script>
I'm not sure this is supported. You might have to implement this by yourself.
In your updateMaker() method, you could use google.maps.Geocoder() to find the address name yourself:
updateMaker: function(event) {
const geocoder = new google.maps.Geocoder()
geocoder.geocode({ 'latLng': event.latLng }, (result, status) => {
if (status === google.maps.GeocoderStatus.OK) {
// set the input field value with address:
console.log(result[0].formatted_address)
}
})
}
add 'ref' to your auto complete component like :
<GmapAutocomplete ref="gmapAutocomplete" :position.sync="markers[0].position" #keyup.enter="usePlace" #place_changed="setPlace">
</GmapAutocomplete>
Change updateMarker function to this:
updateMaker: function(event) {
console.log('updateMaker, ', event.latLng.lat());
this.markers[0].position = {
lat: event.latLng.lat(),
lng: event.latLng.lng(),
}
const geocoder = new google.maps.Geocoder()
geocoder.geocode({ 'latLng': event.latLng }, (result, status) => {
if (status === google.maps.GeocoderStatus.OK) {
this.$refs.gmapAutocomplete.$refs.input.value = result[0].formatted_address
}
})
},
I've followed google documentation and ended up with this:
function nearbySearchCallback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
console.log(results.length);
for (var i = 0; i < results.length; i++) {
var place = results[i];
createInfoWindow(place.name, place.geometry.location);
//calculateAndDisplayRoute(place.geometry.location.lat(), place.geometry.location.lng());
calculateAndDisplayRoute(place);
break;
}
}
else if(status == google.maps.places.PlacesServiceStatus.ZERO_RESULTS){
//alert("No matching places");
}
else{
alert("Error!");
}
}
function calculateAndDisplayRoute(destObj) {
console.log("id " + destObj.id);
var selectedMode = "Driving";//document.getElementById('mode').value;
console.log("start point: " + locationX + ", " + locationY);
directionsService.route({
origin: {lat: locationX, lng: locationX},
destination: {placeId: destObj.id},
travelMode: google.maps.TravelMode.DRIVING
},
function(response, status) {
if (status == 'OK') {
directionsDisplay.setDirections(response);
} else {
window.alert('Directions request failed due to ' + status);
}
});
}
The response is: Directions request failed due to NOT_FOUND
Why is this happening?
locationX and locationY are lat/lng from gps and i am pretty sure that the destObj is a shop near my location. So why google says it can't find any routes?
If I change origin/destination to arbitrary locations from googles docs:
origin: {lat: 37.77, lng: -122.447}, // Haight.
destination: {lat: 37.768, lng: -122.511}, // Ocean Beach.
then it starts to work
You have a typo in your code .id is not the placeId in the place object. According to the documentation for PlaceResult, that is .place_id.
proof of concept fiddle
code snippet:
var geocoder;
var map;
var directionsService = new google.maps.DirectionsService;
var directionsDisplay = new google.maps.DirectionsRenderer;
function initialize() {
map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
directionsDisplay.setMap(map);
var service = new google.maps.places.PlacesService(map);
service.nearbySearch({
location: map.getCenter(),
radius: 500,
type: ['store']
}, nearbySearchCallback);
}
google.maps.event.addDomListener(window, "load", initialize);
function nearbySearchCallback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
console.log(results.length);
var place = results[3];
calculateAndDisplayRoute(place);
} else if (status == google.maps.places.PlacesServiceStatus.ZERO_RESULTS) {
//alert("No matching places");
} else {
alert("Error!");
}
}
function calculateAndDisplayRoute(destObj) {
console.log("id " + destObj.place_id);
var selectedMode = "Driving";
directionsService.route({
origin: {
lat: map.getCenter().lat(),
lng: map.getCenter().lng()
},
destination: {
placeId: destObj.place_id
},
travelMode: google.maps.TravelMode.DRIVING
},
function(response, status) {
if (status == 'OK') {
directionsDisplay.setDirections(response);
} else {
window.alert('Directions request failed due to ' + status);
}
});
}
html,
body,
#map_canvas {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=places"></script>
<div id="map_canvas"></div>
I try to do a map with seach address/find location and take gps coordinate/find location. I can make to work one by one but I couldn't work them together in one map. These are my google map functions :
Address Search
// When the search form is submitted
jQuery('.js-form-search').on('submit', function(){
GMaps.geocode({
address: jQuery('.js-search-address').val().trim(),
callback: function ($results, $status) {
if (($status === 'OK') && $results) {
var $latlng = $results[0].geometry.location;
$mapSearch.removeMarkers();
$mapSearch.addMarker({ lat: $latlng.lat(), lng: $latlng.lng(), title: 'Adres : '+jQuery('.js-search-address').val()});
$mapSearch.fitBounds($results[0].geometry.viewport);
document.getElementById("lat").value = $latlng.lat();
document.getElementById("long").value = $latlng.lng();
} else {
alert('Adres Bilgisi Bulunamadı ! ');
}
}
});
return false;
});
GPS Location finder
// When the GPS button clicked
jQuery('.js-form-gps').on('submit', function(){
GMaps.geolocate({
success: function(position) {
$mapSearch.setCenter(position.coords.latitude, position.coords.longitude);
$mapSearch.addMarker({
lat: position.coords.latitude,
lng: position.coords.longitude,
animation: google.maps.Animation.DROP,
title: 'GeoLocation',
infoWindow: {
content: '<div class="text-success"><i class="fa fa-map-marker"></i> <strong>Your location!</strong></div>'
}
});
},
error: function(error) {
alert('Geolocation failed: ' + error.message);
},
not_supported: function() {
alert("Your browser does not support geolocation");
},
always: function() {
// Message when geolocation succeed
}
});
return false;
});
};
How can I entegrate two of them ?
Thanks,
I want to find the location name which user select on map.
Currently I am getting latitude and longitude both.
But unable to get the location name.
I am using angularJS and angular-google-maps 2.1.5.
Here is the html.
<ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="true" options="options" events="map.events">
</ui-gmap-google-map>
JS :
$scope.map = {
center: {
latitude: 21.0000,
longitude: 78.0000
},
zoom: 4,
events: {
click: function(mapModel, eventName, originalEventArgs,ok) {
var e = originalEventArgs[0];
objOneDevice.dev_latitude = e.latLng.lat();
objOneDevice.dev_longitude = e.latLng.lng();
$scope.templatedInfoWindow.show = true;
}
}
};
$scope.options = {
scrollwheel: true
};
Anything is appreciated.
Here what I have done using Reverse geocoding.
$scope.map = {
center: {
latitude: 21.0000,
longitude: 78.0000
},
zoom: 4,
events: {
click: function(mapModel, eventName, originalEventArgs,ok) {
var e = originalEventArgs[0];
var geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(e.latLng.lat(), e.latLng.lng());
geocoder.geocode({ 'latLng': latlng }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
console.log(results[1].formatted_address); // details address
} else {
console.log('Location not found');
}
} else {
console.log('Geocoder failed due to: ' + status);
}
});
}
}
};
Given Latitude/Longitude object you can map location to approximate address using Google Map API.
You can use the Geocoding API for mapping locations to addresses and addresses to locations.
Geocoder.geocode( { 'latLng': latLngObject }, callbackFn);
Here is the link for Google Map API for Geocoding.
Try these links
https://developers.google.com/maps/documentation/javascript/examples/geocoding-reverse?csw=1
Use the Geocoding API for mapping locations to addresses and addresses to locations. http://code.google.com/apis/maps/documentation/javascript/services.html#Geocoding
Geocoder.geocode( { 'latLng': latLngObject }, callback);
http://wbyoko.co/angularjs/angularjs-google-maps-components.html
Hope it helps!!!