I am currently working with Bing maps version 8 . I was previously working with version 7 . When plotting pushpins in version 7 a htmlContent attribute was sent along with the pushpins. What this html content did was that the pushpin was contained inside the div element .
var pushpinOptions = {
htmlContent: "<div id='container" + siteIndex + "'style='pointer-events: all !important; z-index: 35000; '></div><div id='lines"+siteIndex+"'></div>",
anchor:new Microsoft.Maps.Point(iconWidth/2,iconHeight/2),
width: iconWidth,
height: iconHeight
};
var pin = new Microsoft.Maps.Pushpin(latLon, pushpinOptions);
I used Konva JS to plot over these pushpins which i plotted with BingMaps.
var stage = new Konva.Stage({
container: 'container' + siteIndex,
width: width,
height: height,
stroke: 'green'
});
'container' + siteIndex, was the id of the div i set in bing maps pushpins which i used in konva to plot another image over the pushpins. This is my requirement . I have to plot a pushpin with coordinates and then plot some images over the pushpins . Now when i shifted from v7 to v8 for various reasons, I am facing an issue .
In v8 htmlContent is not sent with the pushpins, rather we send an svg image which has no way to identify after being plotted other than co-ordinates .
var customHtml = '<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50"><circle id="myCircle htmlId" cx="25" cy="25" r="20" stroke="orange" stroke-width="4" fill="yellow" /></svg>';
var pin = new Microsoft.Maps.Pushpin(latLon, {
icon: customHtml.replace("htmlId",siteIndex.toString()),
anchor: new Microsoft.Maps.Point(iconWidth/2,iconHeight/2)
});
Now , what i am lokking for is a way to either plot images with a third party api which plots over co-ordinates or find to way to get access of the pushpins i plotted without the html content i.e with svg images. When i access the id with
document.getElementById("myCircle 0");
i get null.
I have looked for many different third party apis like leafleat js, konva js , Graphics js. But i do not find a way to identify my pushpins .
Is there a way to achieve what i wish to? There must be.
HTML pushpins are not supported in Bing Maps V8 as they can't be drawn on an HTML5 canvas. Using SVG would render on the Canvas but there is no DOM element create, which is why you aren't able to use document.getElementById. Using DOM elements with maps really limits performance and is the main reason why rendering is now done with an HTML5 canvas. That said, even in V7 using the approach of custom HTML in general so you can do document.getElementById to retrieve the pushpins was not a good approach. If you want to assign a unique ID to each pushpin and then be able to retrieve it, you should use a custom JavaScript property, or the existing metadata property. For example:
var pin = new Microsoft.Maps.Pushpin(map.getCenter());
pin.metadata = {
id: 'myCircle 0'
};
map.entities.push(pin);
function getPushpinById(id){
var pin;
for(var i=0,len = map.entities.getLength(), i<len;i++){
pin = map.entities.get(i);
if(pin.metadata && pin.metadata.id === id){
return pin;
}
}
}
Using this approach would allow the greatest performance in your app. However, if you really want to use custom HTML to create pushpins, it is possible to achieve this in V8 by using a custom overlay. Here is a code sample: https://msdn.microsoft.com/en-US/library/mt762877.aspx
Related
Just a quick question, if anyone has ever replaced the Mapbox default marker with a Maki icon. I've only seen examples of using Maki icons for point tilesets/layers, but I'm wanting to use it for non-tileset features, specifically replacing the marker that adds after geocoding, at the location of the address just geocoded.
Or, trying to find something that is similar to Google Maps symbols below. Any suggestions appreciated.
var pinImage = {
path: google.maps.SymbolPath.CIRCLE,
fillColor: '#ff4b00',
fillOpacity: .9,
scale: 5,
strokeColor: '#CDDC39',
strokeWeight: 0,
strokeOpacity: .5
}
The MapboxGeocoder control has a marker option https://github.com/mapbox/mapbox-gl-geocoder/blob/master/API.md#parameters which controls the marker placed on the map when you select a result.
There is an example at https://docs.mapbox.com/mapbox-gl-js/example/custom-marker-icons/ to create a Marker with a custom icon.
So you could create an HTML Element which contains either an SVG or PNG icon from Maki and use that as your element in your custom Marker passed to the MapboxGeocoder control.
I think this sample is what you are looking for Use a custom render function with a geocoder
It allows you to add a custom render function including the icon...
var geocoder = new MapboxGeocoder({
accessToken: mapboxgl.accessToken,
types: 'poi',
// see https://docs.mapbox.com/api/search/#geocoding-response-object for information about the schema of each response feature
render: function(item) {
// extract the item's maki icon or use a default
var maki = item.properties.maki || 'marker';
return (
"<div class='geocoder-dropdown-item'><img class='geocoder-dropdown-icon' src='https://unpkg.com/#mapbox/maki#6.1.0/icons/" +
maki +
"-15.svg'><span class='geocoder-dropdown-text'>" +
item.text +
'</span></div>'
);
},
mapboxgl: mapboxgl
});
map.addControl(geocoder);
I declare a leaflet map with
<div id="map" class="map-div"></div>
end initialize it with
var map = L.map('map').setView([51.178882, -1.826215],16);
$scope.map = map;
// OSM Mapnik
var osmUrl = "<a href='http://www.openstreetmap.org'>Open StreetMap</a>";
L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© ' + osmUrl,
maxZoom: 18,
}).addTo(map);
I grab some data from my server, and and markers to the map, in a loop, by calling this function (it's AngularJS, but I doubt that that plays a role):
$scope.AddMarkerToMap = function(companyData, index, array)
{
var companyName = companyData.company_name;
var latitude = companyData.latitude;
var longitude = companyData.longitude;
var cssClassname = 'comapny_has_no_present_workers';
if (companyData['currentWorkers'] > 0)
cssClassname = 'comapny_has_present_workers';
var pubLatLng = L.latLng(latitude,longitude);
// see https://leafletjs.com/reference-1.4.0.html#marker
var marker = L.marker(pubLatLng,
{
// this is the tooltip hover stuff
title: companyData['currentWorkers'] + ' current matches ' + companyData['previousWorkers'] + ' previous matches',
// see https://leafletjs.com/reference-1.4.0.html#icon
// this is a permanent label.
icon: new L.DivIcon({
className: cssClassname,
////html: '<img class="my-div-image" src="http://png-3.vector.me/files/images/4/0/402272/aiga_air_transportation_bg_thumb"/>'+
//// '<span class="my-div-span">RAF Banff Airfield</span>'
html: '<span>' + companyName + '</span>'
})
}).addTo($scope.map);
// see https://leafletjs.com/reference-1.4.0.html#popup
marker.bindPopup("<b>Hello world!</b><br>I am a popup.").openPopup();
}; // AddMarkerToMap()
And the entire map is suddenly grey - with no problems reported in the developer console.
If I comment out the line
marker.bindPopup("<b>Hello world!</b><br>I am a popup.").openPopup();
then everything displays as expected.
The code seems correct, as per the Leaflet documentation.
[Updtae] I just checked and if I only marker.bindPopup("<b>Hello world!</b><br>I am a popup."), the the map displays and I can click on the marker to display the popup. But when I try to programmatically open it with .openPopup(); the map is all grey.
[Update++] the map and its markers display just fine, with any one of
marker.bindPopup("<b>Hello world!</b><br>I am a popup.");
$scope.map.fitBounds(bounds, {padding: [50, 50]});
but with both, the map is grey :-(
What am I doing wrongly?
I think the issue comes from trying to change the map view (possibly through openPopup with autoPan, which is on by default) too often, typically in a loop without giving any delay for the map to actually set the view between each call.
IIRC, this is already identified as a limitation in Leaflet, but I could not find the exact thread in the issue tracker unfortunately.
Normally, a very simple fix is simply to remove the map view changes within your loop, and keep only the very last one.
In your case, if you have the default behaviour of only 1 Popup being opened at a time, then that would definitely be a valid solution: just open the popup of your last Marker.
If you did configure your map to keep several Popups open simultaneously, and you do want to open all of them through your loop, then make sure to disable autoPan (at least during your loop).
I am exporting Google Directions routes as KML and displaying them on a Mapbox map by reading them with Omnivore and adding them to the map,
The Google KML stores each route as two Places (the start and end points) and one LineString (the route). In Mapbox I would like to show only the routes, that is to filter out the markers somehow. I'm displaying markers out of my own database and the Google markers clutter it up.
Here is my code. I change the styling of the LineStrings just to show that I can, but do not know what magic call(s) to make to not display the Points.
Thanks.
runLayer = omnivore.kml('data/xxxx.kml')
.on('ready', function() {
var llBnds = runLayer.getBounds();
map.fitBounds(llBnds);
this.eachLayer(function (layer) {
if (layer.feature.geometry.type == 'LineString') {
layer.setStyle({
color: '#4E3508',
weight: 4
});
}
if (layer.feature.geometry.type == 'Point') {
//
// Do something useful here to not display these items!!
//
}
});
})
.addTo(map);
Welcome to SO!
Many possible solutions:
Most straight forward from the code you provided, just use the removeLayer method on your runLayer Layer Group when you get a 'Point' feature.
Cleaner solution would be to filter out those features before they are even converted into Leaflet layers, through a custom GeoJSON Layer Group passed as 3rd argument of omnivore.kml, with a specified filter option:
var customLayer = L.geoJSON(null, {
filter: function(geoJsonFeature) {
// my custom filter function: do not display Point type features.
return geoJsonFeature.geometry.type !== 'Point';
}
}).addTo(map);
var runLayer = omnivore.kml('data/xxxx.kml', null, customLayer);
You can also use the style and/or onEachFeature options on customLayer to directly apply your desired style on your LineString.
First of all I would like to thank you all for amazing libraries like leaflet/leaflet.draw and leaflet.snap.
What I want to do is outside leaflet.draw control with supporting leaflet snap. This is nicely working with in side map draw control.
Below I show how did I call outside leaflet draw control:
<div><button id="draw_mark1" onclick="drawMarker1()" >Draw Marker1</button></div>
<div><button id="draw_polyline1" onclick="drawPolyline1()" >Draw Polyline1</button></div>
function drawMarker1(){
var markerDrawer1 = new L.Draw.MarkerA(map, { icon: new myIcon_xx() });
markerDrawer1.enable();
}
function drawPolyline1(){
var polylineDrawer1 = new L.Draw.PolylineType1(map);
polylineDrawer1.enable();
}
note:- leaflet.snap not in the tag list. I want to tag it too.
In internet explorer 8, none of my polygons on my bing maps have the proper fill color. They are always filled in white. I have no issues in firefox, chrome, safari or opera.
I've even tried using the exact code from the bing docs
// Initialize the map
var map = new Microsoft.Maps.Map(document.getElementById("mapDiv"), {credentials:"Bing Maps Key"});
// Create the locations
var location1 = new Microsoft.Maps.Location(20,-20);
var location2 = new Microsoft.Maps.Location(20,20);
var location3 = new Microsoft.Maps.Location(-20,20);
var location4 = new Microsoft.Maps.Location(-20,-20);
// Create a polygon
var vertices = new Array(location1, location2, location3, location4, location1);
var polygoncolor = new Microsoft.Maps.Color(100,100,0,100);
var polygon = new Microsoft.Maps.Polygon(vertices,{fillColor: polygoncolor, strokeColor: polygoncolor});
// Add the shape to the map
map.entities.push(polygon)
// Set the view
map.setView({bounds: Microsoft.Maps.LocationRect.fromLocations(vertices)});
Has anyone experienced this?
I am also using jquery 1.5.1
Figured out the issue.
I was using a htc file (ie-css3.htc) for some css3 effects in IE. I guess this doesn't play nicely with bing maps polygon colors.