How to disable mobile touch event after the bing map is initialized?
We can disable before initializing by below code, using MapOptions object. However I'm looking after the Bing Map is initialized.
// Set the map and view options, setting the map style to Road and
// removing the user's ability to change the map style
var mapOptions = {credentials:"Bing Maps Key",
height: 400,
width: 400,
mapTypeId: Microsoft.Maps.MapTypeId.road,
disableTouchInput : true,
};
// Initialize the map
var map = new Microsoft.Maps.Map(document.getElementById("mapDiv"), mapOptions);
Any help is highly appreciated. Thanks in advance!!!
Most of the MapOptions do work when passed into the setOptions method of the map. For instance try this: map.setOptions({disableTouchInput: true});
Note that I've only tested this in IE. If you simply want to disable panning and zooming you can do this in a number of different ways. The first is to use map options, the other is to use the viewchange event, store the original map position and keep setting the map to the same view to lock it.
Since you can't set most of the MapOptions once the map is created you can only do this by swapping out your map for a new map with the options you want. This is a very basic example, but here is an example that shows and hides the bing logo which is one of the settings that you can't change with setOptions.
function switchMapOptions(active, inactive) {
try {
var newMap = new MM.Map($(inactive)[0], options);
for (var i = 0; i < map.entities.getLength(); i++) {
var loc = map.entities.get(i).getLocation();
newMap.entities.push(new MM.Pushpin(loc));
}
newMap.setView({center: map.getCenter(), zoom: map.getZoom(), animate: false});
map.dispose();
map = newMap;
}
catch (e) {
alert(e.message);
}
}
Full code at Jsfiddle: http://jsfiddle.net/bryantlikes/zhH5g/4/
Related
Using leaflet is there any way I can get the bounds (NorthEast, SouthWest) of a loaded tile? I want to request the server to load the markers only for a particular tile which is loaded, so that when user is panning/dragging the map he can easily see the new markers on new area.
What you really want to do is a subclass of L.GridLayer. This will allow fine control over loaded/unloaded tiles, and is the best way to use the private L.GridLayer._tileCoordsToBounds() method.
With some basic handling of loaded markers, it should look like:
L.GridLayer.MarkerLoader = L.GridLayer.extend({
onAdd: function(map){
// Add a LayerGroup to the map, to hold the markers
this._markerGroup = L.layerGroup().addTo(map);
L.GridLayer.prototype.onAdd.call(this, map);
// Create a tilekey index of markers
this._markerIndex = {};
},
onRemove: function(map){
this._markergroup.removeFrom(map);
L.GridLayer.prototype.onRemove.call(this, map);
};
createTile: function(coords, done) {
var tileBounds = this._tileCoordsToBounds(coords);
var tileKey = this._tileCoordsToKey(coords);
var url = ...; // Compute right url using tileBounds & coords.z
fetch(url).then(function(res){
if (!key in this._markerIndex) { this._markerIndex[key] = []; }
// unpack marker data from result, instantiate markers
// Loop as appropiate
this._markerGroup.addLayer(marker);
this._markerIndex[key] = marker;
done(); // Signal that the tile has been loaded successfully
});
},
_removeTile: function (key) {
for (var i in this._markerIndex[key]) {
this._markerGroup.remove(this._markerIndex[key][i]);
}
L.GridLayer.prototype._removeTile.call(this, key);
}
});
Please note that zooming might be a source of bugs and graphical glitches (markers being removed because a tile unloads, before the markers at the new zoom level are loaded). Beware of that.
I'm still learning and I'm a bit stuck. I may be trying to do to much at once. I have a MapBox map working great with a clickable layer menu taken from examples on the MapBox site. I also have a MarkerClusterGroup which also works and is always visible on the map. Is there a way I could somehow have the MarkerClusterGroup clickable on/off just like layers identified in var overlays = { ...
Below is the code that I think needs the help:
var layers = {
Streets: L.mapbox.tileLayer('mapbox.streets').addTo(map),
Satellite: L.mapbox.tileLayer('mapbox.satellite'),
Light: L.mapbox.tileLayer('mapbox.light'),
};
var overlays = {
DataA: L.mapbox.featureLayer().loadURL('/data/ctsnew.geojson'),
DataB: L.mapbox.featureLayer().loadURL('/data/selectZipcodes.geojson'),
};
// Since featureLayer is an asynchronous method, we use the `.on('ready'`
// call to only use its marker data once we know it is actually loaded.
Markers: L.mapbox.featureLayer('examples.map-h61e8o8e').on('ready', function(e) {
// The clusterGroup gets each marker in the group added to it
// once loaded, and then is added to the map
var clusterGroup = new L.MarkerClusterGroup();
e.target.eachLayer(function(layer) {
clusterGroup.addLayer(layer);
});
map.addLayer(clusterGroup);
});
Could be something as simple as misuse of brackets. Thanks in advance.
You have to include your Marker Cluster Group in your overlays object. For example you could instantiate it just before defining overlays, even if your Cluster Group is empty for now.
Then you fill it once it has downloaded its data.
var layers = {
Streets: L.mapbox.tileLayer('mapbox.streets').addTo(map),
Satellite: L.mapbox.tileLayer('mapbox.satellite'),
Light: L.mapbox.tileLayer('mapbox.light'),
};
var clusterGroup = L.markerClusterGroup();
var overlays = {
DataA: L.mapbox.featureLayer().loadURL('/data/ctsnew.geojson'),
DataB: L.mapbox.featureLayer().loadURL('/data/selectZipcodes.geojson'),
Markers: clusterGroup
};
// Since featureLayer is an asynchronous method, we use the `.on('ready'`
// call to only use its marker data once we know it is actually loaded.
L.mapbox.featureLayer('examples.map-h61e8o8e').on('ready', function(e) {
// The clusterGroup gets each marker in the group added to it
// once loaded, and then is added to the map
e.target.eachLayer(function(layer) {
clusterGroup.addLayer(layer);
});
map.addLayer(clusterGroup); // use that line if you want to automatically add the cluster group to the map once it has downloaded its data.
});
I'm trying to update the lat/lng value of a marker after it is moved. The example provided uses a popup window to display the lat/lng.
I have a "dragend" event listener for the marker, but when I alert the value of e.latlng it returns undefined.
javascript:
function markerDrag(e){
alert("You dragged to: " + e.latlng);
}
function initialize() {
// Initialize the map
var map = L.map('map').setView([38.487, -75.641], 8);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA',
maxZoom: 18
}).addTo(map);
// Event Handlers
map.on('click', function(e){
var marker = new L.Marker(e.latlng, {draggable:true});
marker.bindPopup("<strong>"+e.latlng+"</strong>").addTo(map);
marker.on('dragend', markerDrag);
});
}
$(document).ready(initialize());
http://jsfiddle.net/rhewitt/Msrpq/4/
Use e.target.getLatLng() to get the latlng of the updated position.
// Script for adding marker on map click
function onMapClick(e) {
var marker = L.marker(e.latlng, {
draggable:true,
title:"Resource location",
alt:"Resource Location",
riseOnHover:true
}).addTo(map)
.bindPopup(e.latlng.toString()).openPopup();
// #12 : Update marker popup content on changing it's position
marker.on("dragend",function(e){
var chagedPos = e.target.getLatLng();
this.bindPopup(chagedPos.toString()).openPopup();
});
}
JSFiddle demo
latlng value is not in e.latlng but in e.target._latlng .
Use console.
While using e.target._latlng works (as proposed by this other answer), it's better practice to use
e.target.getLatLng();
That way we're not exposing any private variables, as is recommended by Leaflet:
Private properties and methods start with an underscore (_). This doesn’t make them private, just recommends developers not to use them directly.
I think the API changed.
Nowadays is: const { lat, lng } = e.target.getCenter();
if anyone is using react than you should use :
const map = useMap()
map.addEventListener("dragend" , ()=> {
const {lat , lng} = map.getCenter()
})
I am creating a map page with a single image,
and I would like to use GeoLocation to show where the user is as a blue dot (somewhat like iOS maps).
I already have the JavaScript for finding the location, and it works great.
I just need help with how to place a marker - just a simple image - on the page according to the output of position.coords.latitude and position.coords.longitude.
Is there any way that this can be done, and if so, how?
Thanks in advance.
You can simply use GMarker in your javascript, something like this:
var myLatlng = new google.maps.LatLng(-25.363882,131.044922);
var mapOptions = {
zoom: 4,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title:"Hello World!"
});
You can customize its image like that:
var image = 'beachflag.png';
marker.icon = image;
I've an issue with the leaflet openPopup method.
showMap = function(elements) {
var jsonp = 'http://a.tiles.mapbox.com/v3/blahblahblah.jsonp';
var m = new L.Map("my_map").setView(new L.LatLng(51.5, -0.09), 15);
var geojsonLayer = new L.GeoJSON();
var PlaceIcon = L.Icon.extend({
iconSize: new L.Point(25, 41),
shadowSize: new L.Point(40, 35),
popupAnchor: new L.Point(0, -30)
});
var icon = new PlaceIcon(__HOME__ + '/images/leaflet/marker.png');
var marker;
for (var i = 0; i < elements.length; i++) {
var address = $("<div/>").html(elements[i].address).text();
var latlng = new L.LatLng(elements[i].latitude, elements[i].longitude);
marker = new L.Marker(latlng, {icon: icon}).bindPopup(address);
if (i == 0) {
marker.openPopup();
}
m.addLayer(geojsonLayer).addLayer(marker);
}
// Get metadata about the map from MapBox
wax.tilejson(jsonp, function(tilejson) {
m.addLayer(new wax.leaf.connector(tilejson));
});
}
When I click on a marker I have the popup open. But I would like to have the first popup open when the map is loaded. (and open other popups on markers click)
AnNy ideas ?
Put openPopup call after you add the marker to the map and you should be fine.
I'm assuming that when you click on a marker you see the popup but you're not getting the popup of the first marker to show automatically when the map is loaded?
First, it doesn't look like you're actually using GeoJSON so a GeoJSON layer isn't necessary (you can just use a FeatureLayer) but that shouldn't cause any issues. Whatever layer group you use you should only be adding it to the map once and then adding all child layers to the LayerGroup. You're currently adding the geojsonLayer multiple times in your "for" loop which you don't want to do.
Second, you have to call marker.openPopup() after the marker is added to the map.
Try changing your code around to looks something like this:
var layerGroup = new L.FeatureGroup();
layerGroup.addTo( m );
for (var i = 0; i < elements.length; i++) {
var address = $("<div/>").html(elements[i].address).text();
var latlng = new L.LatLng(elements[i].latitude, elements[i].longitude);
marker = new L.Marker(latlng, {icon: icon}).bindPopup(address);
//You don't add the marker directly to the map. The layerGroup has already
//been added to the map so it will take care of adding the marker to the map
layerGroup.addLayer( marker );
if (i == 0) {
marker.openPopup();
}
}
I had this issue and fixed it with adding a timeout right after I added the marker on the map.
marker.addTo(this.map).bindPopup('Info');
setTimeout(() => {
marker.openPopup();
}, 500);
I don't know why but on some page, I need to apply timeout. In any case it's my workaround, hope this works for some of you too.
First add your map then put openPopup():
L.marker([lat, long]).bindPopup('Your message').addTo(map).openPopup();