I'm using google directions to display route on a map after visitors set origin address.
But after using this code which works :
direction.setDirections(response)
I can't refresh my map with:
google.maps.event.trigger(map, "resize");
jQuery(document).ready(function($){
var calculate;
var direction;
var panel;
var map = null;
var center;
panel = document.getElementById('panel');
$('.bandeau').hide();
function new_map( $el ) {
var $markers = $el.find('.marker');
var maOptions = {
zoom : 7,
center : new google.maps.LatLng(0, 0),
scaleControl: false,
scrollwheel: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// création de la carte
map = new google.maps.Map( $el[0], maOptions);
// ajout de la référence du marqueur
map.markers = [];
// création du marqueur
$markers.each(function(){
add_marker( $(this), map );
});
// centrer la carte
center_map( map );
// renvoyer la carte
return map;
}
/*
* Ajout d'un marqueur
*/
function add_marker( $marker, map ) {
var latlng = new google.maps.LatLng( $marker.attr('data-lat'), $marker.attr('data-lng') );
// creation d'un marqueur
var marker = new google.maps.Marker({
position : latlng,
map : map
});
// ajout au tableau
map.markers.push( marker );
}
/*
* Centrer la carte
*/
function center_map( map ) {
var bounds = new google.maps.LatLngBounds();
// Boucler sur tous les marqueurs
$.each( map.markers, function( i, marker ){
var latlng = new google.maps.LatLng( marker.position.lat(), marker.position.lng() );
bounds.extend( latlng );
});
// Si un seul marqueur
if( map.markers.length == 1 )
{
// le centrer sur la carte
map.setCenter( bounds.getCenter() );
map.setZoom( 14 );
}
else
{
map.fitBounds( bounds );
}
}
/*
* affichage carte
*/
$(document).ready(function(){
$('.ms-map-ctc').each(function(){
// Création de la carte
map = new_map( $(this) );
google.maps.event.addDomListener(map, 'idle', function() {
center = map.getCenter();
});
direction = new google.maps.DirectionsRenderer({
map : map,
panel : panel // Dom element pour afficher les instructions d'itinéraire
});
});
});
/*
* Itinéraire
*/
$( "#direction" ).on('submit', function(e) {
e.preventDefault();
origin = document.getElementById('ms-origin').value; // Le point de départ
destination = 'Paris France'; // Le point d'arrivée
if(origin && destination){
var request = {
origin : origin,
destination : destination,
travelMode : google.maps.DirectionsTravelMode.DRIVING // Mode de conduite
}
var directionsService = new google.maps.DirectionsService(); // Service de calcul d'itinéraire
directionsService.route(request, function(response, status){ // Envoie de la requête pour calculer le parcours
if(status == google.maps.DirectionsStatus.OK){
center = map.getCenter();
// On redimensionne la carte pour afficher l'itinéraire à côté
$('.bandeau').show( 200, function() {
$('#ms-map-ctc').addClass('resized-map');
});
direction.setDirections(response); // Trace l'itinéraire sur la carte et les différentes étapes du parcours
google.maps.event.trigger(map, "resize");
map.setCenter(center);
}
});
}
});
/*
* Places
*/
var lenItin = $('#ms-origin').length;
if (lenItin != 0) {
var autocomplete;
autocomplete = new google.maps.places.Autocomplete(
(document.getElementById('ms-origin')),
{ types: ['geocode'] }
);
}
});
.bandeau{
width: 100%;
height: 40px;
background: #000;
}
#ms-map-ctc{
position: relative;
width: 100%;
height: 50vh;
}
#ms-map-ctc.resized-map{
width: 70%;
height: 90vh;
}
#panel{
position: absolute;
top: 0; right: 0;
width: 30%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=places&signed_in=false" type="text/javascript"></script>
<div class="bandeau"></div>
<div class="gm-wrap-ctc">
<div id="ms-map-ctc" class="ms-map-ctc">
<div class="marker" data-lat="48.854546" data-lng="2.349958"></div>
</div>
</div>
<form action="" method="get" name="direction" id="direction">
<input type="text" name="origin" id="ms-origin">
<input id="ms-bt-calc" type="submit" value="Calculer votre itinéraire / Calculate your route">
</form>
<div id="panel"></div>
If you set "Toulouse" for example, and validate, you'll see that we need another validate to zoom and refresh the map. The black header is normal and yes I replace element to have the route description on the side.
On my website I got grey zones but I can't repeat it here but I think the problem is the same.
Of course, once we use it, it works after.
A good french developper, Matthieu Rebillard found the answer :
I had a css transition on the map. Css transitions and javascript refresh couldn't work together. I removed the css transition and everything work now :)
Related
I've built a store locator using the following guide but would love to zoom back out to the zoom level I've set on page load when closing the pop-up.
https://docs.mapbox.com/help/tutorials/building-a-store-locator/
Right now nothing happens after closing the poup-up and the user is forced to zoom out themselves to view the full map. Has anyone figured anything out?
mapboxgl.accessToken = 'pk.eyJ1IjoibmNoZXN0ZXI5MTkiLCJhIjoiY2t3NWFqaWliMG9zNzJ3bzhlMWQ3aXEyNyJ9.T_Z0pW3w6tZOftLeoJU-fA';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/nchester919/ckw5pnpyp0tfp14s5xo5trf4b',
center: [ -79.019302, 35.759575],
zoom: 6,
scrollZoom: true
});
map.addControl(new mapboxgl.FullscreenControl({container: document.querySelector('page-template')}));
const nav = new mapboxgl.NavigationControl({
showZoom: true,
showCompass: true,
});
map.addControl(nav, 'top-right');
const popup = new mapboxgl.Popup({
closeButton: true,
});
const stores = {
"type": "FeatureCollection",
"features": [
$lat = get_sub_field('latitude');
$log = get_sub_field('longitude');
$county = get_sub_field('county');
$region = get_sub_field('region') ?: 'central';
$city = get_sub_field('city');
$image = get_sub_field('image') ?: get_template_directory_uri().'/img/retire-home.jpg';
$desc = esc_html(get_sub_field('desc'));
$phone = get_sub_field('phone');
$address = esc_html(get_sub_field('address'));
$url = get_sub_field('url');
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
<?php echo '-'.$log; ?>,
<?php echo $lat; ?>
]
},
"properties": {
"phoneFormatted": "<?php echo $phone; ?>",
"county": "<?php echo $county; ?>",
"desc": "<?php echo $desc; ?>",
"url": "<?php echo $url; ?>",
"urlp": "<?php echo parse_url($url, PHP_URL_HOST); ?>",
"region": "<?php echo $region; ?>",
"city": "<?php echo $city; ?>",
"imageUrl": "<?php echo $image; ?>",
}
},
]
};
/* Assign a unique ID to each store */
stores.features.forEach(function (store, i) {
store.properties.id = i;
});
map.on('load', () => {
addMarkers();
map.addSource('places', {
type: 'geojson',
data: stores
});
buildLocationList(stores);
});
function addMarkers() {
/* For each feature in the GeoJSON object above: */
for (const marker of stores.features) {
/* Create a div element for the marker. */
const el = document.createElement('div');
/* Assign a unique `id` to the marker. */
el.id = `marker-${marker.properties.id}`;
/* Assign the `marker` class to each marker for styling. */
el.className = `marker marker-${marker.properties.region}`;
/**
* Create a marker using the div element
* defined above and add it to the map.
**/
new mapboxgl.Marker(el, { offset: [0, -23] })
.setLngLat(marker.geometry.coordinates)
.addTo(map);
el.addEventListener('click', (e) => {
/* Fly to the point */
flyToStore(marker);
/* Close all other popups and display popup for clicked store */
createPopUp(marker);
/* Highlight listing in sidebar */
const activeItem = document.getElementsByClassName('active');
e.stopPropagation();
if (activeItem[0]) {
activeItem[0].classList.remove('active');
}
const listing = document.getElementById(`listing-${marker.properties.id}`);
listing.classList.add('active');
});
}
}
function buildLocationList(stores) {
for (const store of stores.features) {
/* Add a new listing section to the sidebar. */
const listings = document.getElementById('listings');
const listing = listings.appendChild(document.createElement('div'));
/* Assign a unique `id` to the listing. */
listing.id = `listing-${store.properties.id}`;
/* Assign the `item` class to each listing for styling. */
listing.className = `ccpop_item ccmap-${store.properties.region}`;
/* Add the link to the individual listing created above. */
const link = listing.appendChild(document.createElement('a'));
link.href = '#map';
link.className = 'ccpop_link';
link.id = `link-${store.properties.id}`;
link.innerHTML = `Locate on Map`;
link.addEventListener('click', function () {
for (const feature of stores.features) {
if (this.id === `link-${feature.properties.id}`) {
flyToStore(feature);
createPopUp(feature);
}
}
const activeItem = document.getElementsByClassName('active');
if (activeItem[0]) {
activeItem[0].classList.remove('active');
}
this.parentNode.classList.add('active');
});
/* Add details to the individual listing. */
const details = listing.appendChild(document.createElement('div'));
details.innerHTML = `<div class="ccpop_county">${store.properties.county}</div>`;
if (store.properties.city) {
details.innerHTML += `<div class="ccpop_address">${store.properties.city}</div>`;
}
if (store.properties.url) {
details.innerHTML += `<a class="ccpop_urllist" target="_blank" href="${store.properties.url}">${store.properties.urlp}</a>`;
}
if (store.properties.distance) {
const roundedDistance = Math.round(store.properties.distance * 100) / 100;
details.innerHTML += `<div><strong>${roundedDistance} miles away</strong></div>`;
}
}
}
function flyToStore(currentFeature) {
map.flyTo({
center: currentFeature.geometry.coordinates,
zoom: 15
});
jQuery('.mapboxgl-popup-close-button').on('click', function () {
map.zoomOut({
center: [ -79.019302, 35.759575],
zoom: 6,
scrollZoom: true
});
});
}
function createPopUp(currentFeature) {
const popUps = document.getElementsByClassName('mapboxgl-popup');
/** Check if there is already a popup on the map and if so, remove it */
if (popUps[0]) popUps[0].remove();
const popup = new mapboxgl.Popup({ closeOnClick: true })
.setLngLat(currentFeature.geometry.coordinates)
.setHTML(`<div style="background-image: url('${currentFeature.properties.imageUrl}');" class="ccpop_image"></div><header class="ccpop_heading">${currentFeature.properties.county}</header><span class="ccpop_desc">${currentFeature.properties.desc}</span><span class="ccpop_more">More Information</span><a class="ccpop_url" target="_blank" href="${currentFeature.properties.url}">${currentFeature.properties.urlp}</a>`)
.addTo(map);
}
Is it possible to detect state and county based on coordinates from a click on OSM map (US only)?
I can get the coordinated using click event in Leaflet JS:
map.on('click', function(ev) {
console.log(ev.latlng);
});
I can also get location data by doing something l;like this:
map.on("click", function(ev) {
var ln = ev.latlng["lng"],
lt = ev.latlng["lat"];
pt = "https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat="+lt+"&lon="+ln;
});
Which will return json data that looks like this:
https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=28.964162684075685&lon=-98.29776763916017
But I can't seem to be able to figure out what to do next... How do I get the county and state values from it?
You can just fetch, Ajax from jquery or use axios.
let config = {
minZoom: 2,
maxZoom: 18,
};
const zoom = 5;
const lat = 28.964162684075685;
const lng = -98.29776763916017;
const map = L.map("map", config).setView([lat, lng], zoom);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: '© OpenStreetMap contributors',
}).addTo(map);
map.on("click", function(e) {
const { lat, lng } = e.latlng;
const api = `https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}&zoom=18&addressdetails=1`;
fetchData(api).then((data) => {
const { county, state } = data.address;
console.log(county, state);
});
});
async function fetchData(url) {
try {
const response = await fetch(url);
const data = await response.json();
return data;
} catch (err) {
console.error(err);
}
}
*,
:after,
:before {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html {
height: 100%;
}
body,
html,
#map {
width: 100%;
height: 100%;
}
body {
position: relative;
min-height: 100%;
margin: 0;
padding: 0;
background-color: #f1f1f1;
}
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" rel="stylesheet" />
<div id="map"></div>
I have a map with a layer control that has overlays specified in the baselayer parameter:
var overlays = {
'Layer 1': mylayer1,
'Layer 2': mylayer2
};
L.control.layers( overlays, null, { collapsed: false } ).addTo( map );
I specify my layers as follows:
var mylayer1 = L.esri.featureLayer({
url: 'https://.../MapServer/5'
}).on( 'load', function ( e ) {
...
}).on( 'loading', function ( e ) {
...
}).bindPopup( function ( layer ) {
return L.Util.template( '<p>{_score}</p>', layer.feature.properties );
});
The issue is that when I change layers in the control the bindPopup event no longer gets called.
It's almost like the layer z-index is not updated. Would appreciate any insight on how I can address this.
See: https://codepen.io/jvanulde/pen/LYyOWZo
I see no one has given an answer.
A little around, but it works.
You add the id: x to each layer. Later in the loop you check which layer is active, and all the rest of the layers you add the style display: none.
window.addEventListener('DOMContentLoaded', () => {
let tiles = L.tileLayer('//{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors, Points © 2012 LINZ'
});
let l1 = L.esri.featureLayer({
url: 'https://maps-cartes.services.geo.ca/server_serveur/rest/services/NRCan/nhsl_en/MapServer/1',
id: 0, // required
simplifyFactor: 0.25,
precision: 5,
fields: ['OBJECTID'],
renderer: L.canvas()
}).bindPopup(function(layer) {
return L.Util.template('<p>Layer 1: <strong>{OBJECTID}</strong></p>', layer.feature.properties);
});
let l2 = L.esri.featureLayer({
url: 'https://maps-cartes.services.geo.ca/server_serveur/rest/services/NRCan/nhsl_en/MapServer/2',
id: 1, // required
simplifyFactor: 0.25,
precision: 5,
fields: ['OBJECTID'],
renderer: L.canvas()
}).bindPopup(function(layer) {
return L.Util.template('<p>Layer 2: <strong>{OBJECTID}</strong></p>', layer.feature.properties);
});
let map = L.map('map', {
center: [49.2827, -123.1207],
zoom: 12,
layers: [tiles]
});
let overlays = {
'Layer 1': l1,
'Layer 2': l2
};
L.control.layers(overlays, null, {
collapsed: false
}).addTo(map);
l1.addTo(map);
map.on('baselayerchange', function(e) {
const layersCanvas = document.querySelectorAll('.leaflet-overlay-pane > canvas');
layersCanvas.forEach((layer, index) => {
layer.style.display = '';
if (index !== e.layer.options.id) {
layer.style.display = 'none';
}
});
});
});
html {
height: 100%;
}
body {
min-height: 100%;
margin: 0;
padding: 0;
}
#map {
width: 100%;
height: 100vh;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
<script src="https://unpkg.com/esri-leaflet#3.0.2/dist/esri-leaflet.js"></script>
<div id="map"></div>
I want to pin a location when user enter his address information in laravel backpack?
this is Address field in controller
'name' => 'address-input',
'type' => 'customGoogleMaps',
'label' => "Google Maps",
'hint' => 'Help text',
'attributes' => [
'class' => 'form-control map-input',
],
'view_namespace' => 'custom-google-maps-field-for-backpack::fields',
This is customGoogleMaps field (customGoogleMaps.blade.php)
<div #include('crud::inc.field_wrapper_attributes')>
<label>{!! $field['label'] !!}</label>
<input type="text" id="{{ $field['name'] }}" name="{{ $field['name'] }}"
value="{{ old($field['name']) ? old($field['name']) : (isset($field['value']) ? $field['value'] : (isset($field['default']) ? $field['default'] : '' )) }}"
#include('crud::inc.field_attributes')>
<input type="hidden" name="address_latitude" id="address-latitude" value="0" />
<input type="hidden" name="address_longitude" id="address-longitude" value="0" />
<div id="address-map-container" style="width:100%;height:400px; ">
<div style="width: 100%; height: 100%" id="address-map"></div>
</div>
{{-- HINT --}}
#if (isset($field['hint']))
<p class="help-block">{!! $field['hint'] !!}</p>
#endif
</div>
#if ($crud->checkIfFieldIsFirstOfItsType($field, $fields))
{{-- FIELD EXTRA CSS --}}
{{-- push things in the after_styles section --}}
#push('crud_fields_styles')
<!-- no styles -->
#endpush
{{-- FIELD EXTRA JS --}}
{{-- push things in the after_scripts section --}}
#push('crud_fields_scripts')
<!-- no scripts -->
<script
src="https://maps.googleapis.com/maps/api/js?key={{ env('GOOGLE_MAPS_API_KEY') }}&libraries=places&callback=initialize" async defer></script>
<script>
function initialize() {
$('form').on('keyup keypress', function(e) {
var keyCode = e.keyCode || e.which;
if (keyCode === 13) {
e.preventDefault();
return false;
}
});
const locationInputs = document.getElementsByClassName("map-input");
const autocompletes = [];
const geocoder = new google.maps.Geocoder;
for (let i = 0; i < locationInputs.length; i++) {
const input = locationInputs[i];
const fieldKey = input.id.replace("-input", "");
const isEdit = document.getElementById(fieldKey + "-latitude").value != '' && document.getElementById(fieldKey + "-longitude").value != '';
const latitude = parseFloat(document.getElementById(fieldKey + "-latitude").value) || -33.8688;
const longitude = parseFloat(document.getElementById(fieldKey + "-longitude").value) || 151.2195;
const map = new google.maps.Map(document.getElementById(fieldKey + '-map'), {
center: {lat: latitude, lng: longitude},
zoom: 13
});
const marker = new google.maps.Marker({
map: map,
position: {lat: latitude, lng: longitude},
});
marker.setVisible(isEdit);
const autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.key = fieldKey;
autocompletes.push({input: input, map: map, marker: marker, autocomplete: autocomplete});
}
for (let i = 0; i < autocompletes.length; i++) {
const input = autocompletes[i].input;
const autocomplete = autocompletes[i].autocomplete;
const map = autocompletes[i].map;
const marker = autocompletes[i].marker;
google.maps.event.addListener(autocomplete, 'place_changed', function () {
marker.setVisible(false);
const place = autocomplete.getPlace();
geocoder.geocode({'placeId': place.place_id}, function (results, status) {
if (status === google.maps.GeocoderStatus.OK) {
const lat = results[0].geometry.location.lat();
const lng = results[0].geometry.location.lng();
setLocationCoordinates(autocomplete.key, lat, lng);
}
});
if (!place.geometry) {
window.alert("No details available for input: '" + place.name + "'");
input.value = "";
return;
}
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17);
}
marker.setPosition(place.geometry.location);
marker.setVisible(true);
});
}
}
function setLocationCoordinates(key, lat, lng) {
const latitudeField = document.getElementById(key + "-" + "latitude");
const longitudeField = document.getElementById(key + "-" + "longitude");
latitudeField.value = lat;
longitudeField.value = lng;
}
</script>
#endpush
#endif
It display the following Error:
InvalidArgumentException View [inc.field_wrapper_attributes] not found. (View:
C:\xampp\htdocs\CRM\vendor\abr4xas\gmaps-input-backpack\src\resources\views\fields\customGoogleMaps.blade.php)
I've create a map with multiple markes.
Now I'd like to show it in a reveal modal (foundation 6), can someone help me?
I would like to display the google map in a modal reveal, to be visible only when I click on "Open google map".
It seems that what I did does not work properly and I do not understand why.
Look here: http://jsfiddle.net/x6nqL3po/1388/
<div id="map" class="reveal-modal" data-reveal aria-labelledby="modalTitle" aria-hidden="true" role="dialog">
<div id="map"></div>
<a class="close-reveal-modal" aria-label="Close">×</a>
</div>
<div>Click Me For A Modal</div>
<script>
//Google Maps
jQuery(function() {
if ($("#map").length) {
initMap();
}
});
//initMap
function initMap() {
var locations = [
[
"Locatie title 1",
52.147173,
4.470745,
"http://cdn.leafletjs.com/leaflet-0.6.4/images/marker-icon.png",
"city 1",
"Address 1",
"+38/(071)/123/45/67"
],
[
"Locatie title 2",
52.166245,
4.51764,
"https://maps.google.com/mapfiles/ms/micons/blue.png",
"city 2",
"",
"+38/(071)/123/45/67"
],
[
"Locatie title 4",
52.126607,
4.619146,
"https://maps.google.com/mapfiles/ms/micons/blue.png",
"",
"Address 4",
"+38 (071) 123-45-67"
],
];
];
var map = new google.maps.Map(document.getElementById("map"), {
zoom: 9,
center: new google.maps.LatLng(52.159393,4.673784),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var infoWindow = new google.maps.InfoWindow();
var marker, i;
for (i = 0; i < locations.length; i++) {
var lat = locations[i][1];
var lng = locations[i][2];
var pin = locations[i][3];
marker = new google.maps.Marker({
position: new google.maps.LatLng(lat, lng),
animation: google.maps.Animation.DROP,
icon: pin,
map: map
});
google.maps.event.addListener(marker, "click", (function(marker, i) {
var title = (locations[i][0] !== undefined) ? locations[i][0] : '';
var city = (locations[i][4] !== undefined) ? locations[i][4] : '';
var address = (locations[i][5] !== undefined) ? locations[i][5] : '';
var html = ( (title !== '') ? "<h5>" + title + "</h5>" : title ) + ( (city !== '') ? "<h6>" + city + "</h6>" : city ) + ( (address !== '') ? "<p>" + address + "</p>" : address ) ;
return function() {
infoWindow.setOptions({
content:html
});
infoWindow.open(map, marker);
};
//auto center map
map.setCenter(marker.getPosition());
})(marker, i)
);
}
}
function load() {
var map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(30.0599153,31.2620199,13),
zoom: 13,
mapTypeId: 'roadmap'
});
}
</script>
in first place you must change the id of modal container, this should be the same that data-reveal-id on the link (now one is "MyModal" and the other is "map").
Open google map
<div id="myModal" class="reveal-modal">
In your jsfiddle file it seems not loading foundation.css, foundation.js, foundation.reveal.js and jquery, these are necessary as indicated on Reveal Modal Foundation docs (Using the Javascript section)
You can check a updated working version here: http://jsfiddle.net/x6nqL3po/1488/