HERE API - map does not work in safari browser - javascript

im working on a PWA which retrieves the users location via geolocation-API, places a pin to the current location of the user and allows him to drag the pin to a certain location.
this works perfectly in chrome but when testing it in safari, the map only displays the whole world on
the map and doesnt allow zooming further than a few pinches + it doesnt place a marker.
// configure pin
function addDraggableMarker(map, behavior) {
// create icon
var svgMarkup = /* some random svg here */;
var icon = new H.map.Icon(svgMarkup);
// position the pin
var coords = {
lat: lat,
lng: lng
};
// initialize pin
window.marker = new H.map.Marker(
coords, {
icon: icon
}, {
volatility: true
}
);
// make pin draggable
marker.draggable = true;
map.addObject(marker);
// disable the default draggability of the underlying map
map.addEventListener('dragstart', function(ev) {
var target = ev.target,
pointer = ev.currentPointer;
if (target instanceof H.map.Marker) {
var targetPosition = map.geoToScreen(target.getGeometry());
target.offset = new H.math.Point(pointer.viewportX - targetPosition.x, pointer.viewportY - targetPosition.y);
behavior.disable();
}
}, false);
// re-enable the default draggability of the underlying map when dragging has completed
map.addEventListener('dragend', function(ev) {
var target = ev.target;
if (target instanceof H.map.Marker) {
behavior.enable();
window.markerMoved = target.getGeometry();
}
}, false);
// Listen to the drag event and move the position of the marker as necessary
map.addEventListener('drag', function(ev) {
var target = ev.target,
pointer = ev.currentPointer;
if (target instanceof H.map.Marker) {
target.setGeometry(map.screenToGeo(pointer.viewportX - target.offset.x, pointer.viewportY - target.offset.y));
}
}, false);
}
// click on the button which displays the map
$("#addLocation").on('click', function() {
// 1. connect to API
window.platform = new H.service.Platform({
'apikey': 'MY_API_KEY'
});
window.defaultLayers = platform.createDefaultLayers();
// 2. initialize map
window.map = new H.Map(document.getElementById('map'),
defaultLayers.vector.normal.map, {
center: {
lat: lat,
lng: lng
},
zoom: 16,
pixelRatio: window.devicePixelRatio || 1
});
// stretch map to size of container
window.addEventListener('resize', () => map.getViewPort().resize());
// 3. make map interactive
//Behavior implements default interactions for pan/zoom (also on mobile touch environments)
window.behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
// 4. add map UI
window.ui = H.ui.UI.createDefault(map, defaultLayers, "de-DE");
// Add the click event listener.
addDraggableMarker(map, behavior);
});

I copied your code into jsfiddle example and everything works as expected in Safari browser. After clicking the button "AddLocation" the map is displayed at correct location + zoom with marker at the center.
There is one small issue with your code when the Marker is created. volatility property should be next to the icon property:
new H.map.Marker(
coords, {
icon: icon,
volatility: true
}
);

Related

FullscreenControl and Maintaining Map Center

Currently, it appears that if I have say a modestly sized Google Maps display port (300px by 300px) with FullscreenControl enabled, and I center that small map view over a specific area, like... France, for instance... And then I hit the full screen button to expand the display to the edges of my screen (1920px by 1080px), France gets tucked wayyyyy up in the top-left corner of my screen.
Basically, the top-left of the original 300px x 300px display moves to the top-left of my screen, and rest of the world map extends from that corner at the original zoom level.
Is there any way to basically just set it up so that the full screen display opens up having the same center point as the original display, and vice versa when the full screen mode gets closed?
Does toggling the full screen button trigger an event or anything that I can hook a setCenter to?
I compose a code a bit strange but it works perfectly:
<script>
var map;
var center = -1;
var isFullScreen = false;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 8,
center: { lat: -34.397, lng: 150.644 }
});
center = { lat: map.getCenter().lat(), lng: map.getCenter().lng() };
google.maps.event.addDomListener(map, 'bounds_changed', onBoundsChanged);
}
function onBoundsChanged() {
var isFullHeight = $(map.getDiv()).children().eq(0).height() == window.innerHeight;
var isFullWidth = $(map.getDiv()).children().eq(0).width() == window.innerWidth;
if (isFullHeight && isFullWidth && !isFullScreen) {
isFullScreen = true;
map.setCenter(center);
console.log('FULL');
} else if (!isFullWidth||!isFullHeight){
if (isFullScreen) {
map.setCenter(center);
}
isFullScreen = false;
console.log('NOT-FULL');
}
center = { lat: map.getCenter().lat(), lng: map.getCenter().lng() };
}
</script>
I use the bounds_changed event.
If I detect that the map is in full screen I set the map in the center that I note in the precedent event and I set a boolean to true. If the map is not in full screen, I check if the boolean is true, it mean that in the precedent event the map was in full screen, so I recenter the map and next I check if the boolean is false. At the end of the event, I keep the center in a variable fro the next event.
All this are not very clear...
You may consult this post in Stack Overflow.
Notice: This code does not work if you display a single map in all the page of your web app. I do not find a way to remove this bug. Your suggestions are very appreciated, thanks.
Also notice: My code is inspired of the precedent answer. However you can find the same code here. Please notice that it is not a duplicate answer. I add my own part of code in it.
Tell me if you have some questions or comments.
Try this
/** To detect Map Full Screen event */
google.maps.event.addListener( map, 'bounds_changed', onBoundsChanged ); //Event listener map bound change.
var isMapFullScreen = false;
var defaultLocation = {
lat: 27.94,
lng: -82.45
};
function onBoundsChanged() {
if(!isMapFullScreen){
var isFullHeight = $(map.getDiv()).children().eq(0).height() == window.innerHeight;
var isFullWidth= $(map.getDiv()).children().eq(0).width() == window.innerWidth;
if (isFullHeight && isFullWidth) {
isMapFullScreen = true;
myMarker.setPosition(defaultLocation);
map.setCenter(defaultLocation);
console.log('FULL');
} else {
isMapFullScreen = false;
console.log('NOT-FULL');
}
}
}

Get Search Location from Index Page & Zoom to Location on Map Page

I'm trying to setup a redirect from the index page to the map page, so if a user searches for an address using the Places Autocomplete library, they get redirected to the map page with the location that they searched for. The index page does not include a map, but just the search bar with Places Autocomplete library.
The function I've setup on the index page is as follows:
var place;
function indexSearch() {
// Get Address Field and Attach Places Autocomplete
var input = document.getElementById('autocomplete');
var autocomplete = new google.maps.places.Autocomplete(input);
// Get Place When Place_Changed Event if Fired
google.maps.event.addListener(autocomplete, 'place_changed', function () {
place = autocomplete.getPlace();
if (typeof place !== 'undefined') {
window.location.href = 'map';
// Don't know what to do here
// as I can't use map.panTo(place.geometry.location) because
// map does not exist on index page.
}
});
// Erase Previous Address if Search Bar is Clicked
inputIndex.onclick = function () {
inputIndex.value = '';
}
}
Do I need to include something in the initialize() function which is responsible for setting up the map?
function initialize() {
var mapOptions = {
zoom: 17,
center: {
lat: -33.8666,
lng: 151.1958
},
disableDefaultUI: true
};
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
// Catch place and pan map to its location
}
Edit: At least provide a reason for downvote.
I'm looking into using localStorage or sessionStorage. Pass the lat and lng to either of those, and retrieve the location when the map page is loading. Is this an optimal solution? Will update with answer once I have the solution.
Here's what I ended up doing. It's working for me. Hope it helps someone in future.
In indexSearch() function, set a key in sessionStorage to store lat and lng of place that is searched. Capture this information when the place_event is fired.
var place;
function indexSearch() {
// Get Address Field and Attach Places Autocomplete
var input = document.getElementById('autocomplete');
var autocomplete = new google.maps.places.Autocomplete(input);
// Get Place When Place_Changed Event if Fired
google.maps.event.addListener(autocomplete, 'place_changed', function () {
place = autocomplete.getPlace();
if (typeof place !== 'undefined') {
window.location.href = 'map';
// Set key in sessionStorage
sessionStorage.myLat = place.geometry.location.lat();
sessionStorage.myLat = place.geometry.location.lng();
}
});
// Erase Previous Address if Search Bar is Clicked
inputIndex.onclick = function () {
inputIndex.value = '';
}
}
Then in initialize() function, check to see if the key exists. If it does, take the user to that location.
function initialize() {
var mapOptions = {
zoom: 17,
center: {
lat: -33.8666,
lng: 151.1958
},
disableDefaultUI: true
};
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
// Get place from sessionStorage if its exists & pan map to its location
var placeLat = sessionStorage.getItem('myLat');
var placeLng = sessionStorage.getItem('myLng');
if (placeLat && placeLng) {
var searchedPlace = new google.maps.LatLng(placeLat, placeLng);
map.setCenter(searchedPlace);
map.setZoom(15);
}
}

google maps API3 drawing custom map icon based on user selection

Im working on a google maps plugin (there's always room for another right?) and I'm drawing a preview of the map my users will be inserting into their content. Im able to draw everything I set out to, custom content in the info window, setting the location (through places.Autocomplete) etc. The one thing that is escaping me is custom map icon isn't being drawn.
My goal is to have the default icon drawn on first load, and then update it when it changes
Im not getting any 404 or errors in the console, and I've checked my event handlers and they are all working. Can anyone tell me where I've going astray?
Here is what I have so far:
//Initilize the map
google.maps.event.addDomListener(window, 'load', initialize);
function initialize(infowindow) {
var init_center = new google.maps.LatLng(43.703793, -72.326187);
mapOptions = {
center: init_center,
zoom: parseFloat(mapZoomReturn),
mapTypeId: google.maps.MapTypeId.ROADMAP,
scrollwheel : false,
};
var input = document.getElementById('mapAddress');
var autocomplete = new google.maps.places.Autocomplete(input);
var infowindow = new google.maps.InfoWindow();
//var marker = new google.maps.Marker({
// position: init_center,
// map: map,
// icon: mapMarkerImageReturn
//});
// Draw the map
map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
// marker needs to be set after the map
var marker = new google.maps.Marker({
position: init_center,
map: map,
icon: mapMarkerImageReturn
});
// Set up event listeners
// Info window DOM->MAP
google.maps.event.addDomListener(document.getElementById('mapInfoWindow'),
'change', function() {
mapInfoWindowReturn = escape(jQuery('#mapInfoWindow').val());
// get the extra content from feild, by this time the place_changed even will have fired at least once, so we have these values
infowindowPlace = get_info_bubble(locIcon, locName, locAddress, locPhone, locWeb, mapInfoWindowReturn); // returns formatted markup for info bubble
infowindow.setContent(infowindowPlace);
});
// Marker dropdown selection DOM->MAP
google.maps.event.addDomListener(document.getElementById('mapMarker'), 'change', update_maker);
// Custom marker text field DOM->MAP
google.maps.event.addDomListener(document.getElementById('mapMarkerImage'), 'change', update_maker );
function update_maker(){
//update the marker imge - (not working)
markerImage = get_marker_image(); // returns URL as string
marker.setIcon(markerImage);
marker.setPosition(locPlace.geometry.location);
marker.setMap(map);
}
google.maps.event.addListener(autocomplete, 'place_changed', function() {
infowindowPlace = get_info_bubble(locIcon, locName, locAddress, locPhone, locWeb, mapInfoWindowReturn);
infowindow.close();
if (mapMarkerImageReturn !=='' || mapMarkerImageReturn !== false) marker.setVisible(false);
input.className = '';
locPlace = autocomplete.getPlace();
if (!locPlace.geometry) {
// Inform the user that the place was not found and return.
input.className = 'notfound';
return;
}
// If the place has a geometry, then present it on a map.
if (locPlace.geometry.viewport) {
map.fitBounds(locPlace.geometry.viewport);
mapCurrCenter = map.getCenter();
} else {
map.setCenter(locPlace.geometry.location);
map.setZoom(parseFloat(mapZoomReturn));
mapCurrCenter = map.getCenter();
}
// Set the marker image (not working)
markerImage = get_marker_image(); // returns URL as string
marker.setIcon(markerImage);
marker.setPosition(locPlace.geometry.location);
marker.setMap(map);
// get the location values for the info bubble
if (locPlace.address_components) {
//console.log(locPlace.address_components);
// Populate values for info bubble
locName = locPlace.name;
locIcon = locPlace.icon;
locAddress = locPlace.formatted_address;
locPhone = locPlace.formatted_phone_number;
locWeb = locPlace.website;
}
infowindowPlace = get_info_bubble(locIcon, locName, locAddress, locPhone, locWeb, mapInfoWindowReturn);
infowindow.setContent(infowindowPlace);
infowindow.open(map, marker);
});
}

creating multiple infowindows in Bing Maps v7 and presenting data specific to pin

I'm currently trying to learn the Bing Maps API and currently trying to build a map with multiple pins that can be hovered to reveal a info window with that pins data. At the moment I'm experiencing a few problems. If anyone could help with the following points that would be great:
When I mouseleave a pin the info window doesn't get removed?
How can I use the data I retrieve in the addPin() to populate the
required info window?
In createInfoBox() I want to hide any active info window when the
map gets moved but this seems to get triggered even if the map isn't
moved?
If there are any improvements i can make please let me know
jsfiddle: http://jsfiddle.net/kyllle/vpepD/23/ and JS below
JS
var dealerMap = {
createInfoBox: function(infobox) {
var instance = this,
pushpin = infobox;
// Now create infowindows
var NewWindow = new Microsoft.Maps.Infobox(pushpin.getLocation(), {
title: 'title',
offset: new Microsoft.Maps.Point(-3, pushpin.getHeight() - 5),
zIndex: 999,
visible: true
});
//Display infowindow
instance.displayInfoBox(NewWindow, pushpin);
//Hide infowindow if map is moved - currently gets run without moving map
//Microsoft.Maps.Events.addHandler(dealerMap.myMap, 'viewchange', instance.hideInfoBox(NewWindow));
},
displayInfoBox: function(infobox, pin) {
var instance = this;
//Show updated infowindow
dealerMap.myMap.entities.push(infobox);
//Mouse out handler to remove window
Microsoft.Maps.Events.addHandler(pin, 'mouseleave', function() {
instance.hideInfoBox(NewWindow);
});
},
hideInfoBox: function(infobox) {
var instance = this;
console.log('this was called');
dealerMap.myMap.entities.remove(infobox);
},
addPin: function() {
var instance = this;
//make $.ajax json call
var response = data.dummy;
//on success make each pin with returned data
for (var i = 0, len = response.length; i < len; i++) {
var responseItem = response[i],
pinLocation = new Microsoft.Maps.Location(responseItem.lat, responseItem.long);
//Create new pin
var NewPin = new Microsoft.Maps.Pushpin(pinLocation, {
icon: 'http://www.kylehouston.com/testing/sportscar_' + responseItem.id +'.png',
width: 32,
height: 37
});
//Push new pin onto map
this.myMap.entities.push(NewPin);
//Event handlers to show and hide requested infowindow information
Microsoft.Maps.Events.addHandler(NewPin, 'mouseover', function(e) {
console.log(this);
dealerMap.createInfoBox(e.target);
});
}
},
init: function() {
var instance = this;
var mapOptions = {
credentials: "AvGoKWSuMorGQb5h4UyyatCBGmGzSZe7-dWQMzXt4qqz6mV_WCC5m-paxvQhednd",
center: new Microsoft.Maps.Location(37.09024, -95.712891),
zoom: 5,
enableClickableLogo: false,
enableSearchLogo: false
}
dealerMap.myMap = new Microsoft.Maps.Map(document.getElementById('mapDiv'), mapOptions);
//now add some pins
instance.addPin();
}
}
dealerMap.init();
});
I highly recommend only showing one infobox at a time on the map. Showing multiple infoboxes can crowd the map and make for a bad user experience. It also uses up a lot more resources. A better approach is to create a single infobox and reuse it for each pushpin as you want to display content. I wrote a blog post that shows how to do this here: http://rbrundritt.wordpress.com/2011/10/13/multiple-pushpins-and-infoboxes-in-bing-maps-v7/

Google Map mouse wheel bug

Normally it's possible to scroll / zoom vertically out of the map. There would be a grey background. I "disabled / blocked" that.
This works fine if I use the controls from Google map. But if I zoom with the mouse wheel it's kinda buggy and I can zoom out of the map, so the grey area is visible.
Here is a live example: Example
How could I fix that without disabling the mouse wheel zoom?
Image:
THEME.gmap.position = function () {
var allowedBounds;
var lastCenter;
var lastZoom;
var initCenter;
var initZoom;
function checkBounds() {
if (THEME.base.isUndefined(allowedBounds)) {
return false;
}
if (allowedBounds.getNorthEast().lat() > THEME.gmap.google_map.getBounds().getNorthEast().lat()) {
if (allowedBounds.getSouthWest().lat() < THEME.gmap.google_map.getBounds().getSouthWest().lat()) {
lastCenter = THEME.gmap.google_map.getCenter();
lastZoom = THEME.gmap.google_map.getZoom();
return true;
}
}
THEME.gmap.google_map.panTo(lastCenter);
THEME.gmap.google_map.setZoom(lastZoom);
return false;
}
return {
createLatLng:function (lat, lng) {
return new google.maps.LatLng(lat, lng);
},
centerMap:function (latLng) {
THEME.gmap.google_map.setCenter(latLng);
},
setLimit:function () {
allowedBounds = new google.maps.LatLngBounds(
this.createLatLng(-85.0511, -122.591),
this.createLatLng(85.0511, -122.333)
);
initCenter, lastCenter = THEME.gmap.google_map.getCenter();
initZoom, lastZoom = THEME.gmap.google_map.getZoom();
google.maps.event.addListener(THEME.gmap.google_map, 'bounds_changed', function () {
checkBounds();
});
google.maps.event.addListener(THEME.gmap.google_map, 'center_changed', function () {
checkBounds();
});
}
};
}();
I guess this is forced by the 2 competing events, usually both event will fire each time. As the center_changed event is redundant(the bounds also will change when the center changes), you may remove the center_changed-listener(for me this also fixes the issue)

Categories

Resources