The title is not the best explanation. I'm creating a beer flavour graph (no map tiles involved) that uses a custom icon of each beer bottle for each marker. So far so good.
screenshot of the current build
I've got a div outside the map, where I want to display the same bottle png used for the icon (but larger) when each marker is clicked...
for (var i=0; i < markers.length; ++i )
{
var IconVar = L.icon({
iconUrl: markers[i].bottleurl,
shadowUrl: 'images/beer-shadow.png',
iconSize: [36, 120],
shadowSize: [74, 50],
iconAnchor: [16, 60],
shadowAnchor: [35, -26],
popupAnchor: [0, -65]
})
var bigbottleUrl = markers[i].bottleurl;
L.marker( [markers[i].lat, markers[i].lng], {icon: IconVar}, )
.bindPopup( 'Text and some custom content bla bla', customOptions )
.on('click', function(e){document.getElementById("bigbottle").src = bigbottleUrl;}).addTo( beermap );
}
Which works to a point, but defaults to the last marker that is set from a json file. Maybe I can't call different variables from inside the loop, or I haven't set up my loop right.
I've looked through lots of questions here, and tried making it more specific using e.popup._source and this.option and making it specific using _leaflet_id but I'm pushing well beyond my understanding of javascript!
Any ideas?
After going down a few dead ends this was the solution.
var imgUrl;
document.addEventListener('DOMContentLoaded', function() {
document.addEventListener('click', function(event) {
if (event.target.className == 'leaflet-marker-icon leaflet-zoom-animated leaflet-interactive') {
var imgSrc = event.target.src;
var imgFile = imgSrc.substring(imgSrc.lastIndexOf('/')+1);
imgUrl = 'images/' + imgFile;
document.getElementById("bigbottle").src = imgUrl;
}
});
});
There's probably a bit of redundant code, but this was the most efficient way, not putting an onClick event onto everything or having a complex variable that I didn't know how to construct!
Related
I want the marker to be in the center of the map, but it is wrong.
I read the rest of the articles, but my problem was not solved.
var map = L.map('map').setView([lat, lng], 18);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk', {
maxZoom: 18,
id: 'mapbox.streets',
accessToken: 'pk',
attribution: 'nemajoo',
watch: true
}).addTo(map);
var LeafIcon = L.Icon.extend({
options: {
iconSize: [28, 60],
shadowSize: [50, 64],
iconAnchor: [22, 94],
shadowAnchor: [4, 62],
popupAnchor: [-3, -76]
}
});
var greenIcon = new LeafIcon({iconUrl: 'images/mrk.png'});
var center = map.getCenter();
var marker = L.marker([center.lat, center.lng],{icon: greenIcon}).addTo(map);
The problem here could be in any of the 3 configurations given we don't have the image:
mrk.png has some spacing inside the image, this can be fixed with any image editing tool.
the options object, on the anchor tag moves the image, making it look like it's not centered.
When you set the center, as far as I can see, you first get the center from the map, then use this center to position the icon, this is nicely done but markers with distant zooming don't represent it's center accurately.
In resume:
The problem is on the png or the anchor configuration, modify those values and try again.
If this does not work you can upload a sample minimal project so we can check (don't upload api keys or similar)
I'm actually using leaflet into an Angular service, i generate my markers icons with this method:
private getIcon(geoJsonPoint) {
if (geoJsonPoint.properties.actif_id) {
const category = geoJsonPoint.properties.category.toUpperCase();
const prioritie = geoJsonPoint.properties.priority.toUpperCase();
const id = geoJsonPoint.properties.id;
console.log(geoJsonPoint);
const url = 'assets/images/' + category + '/' + prioritie + '.svg';
return L.icon({
iconUrl: url,
className: id,
iconSize: [58, 68],
iconAnchor: [29, 68],
popupAnchor: [0, -60]
});
so on leaflet event (popupen) i want to make my icons bigger without set a new icon but only with css modifications. Is leaflet permits this kind of thing or does someone has already done this ?
Thx for help !
I managed to solve it using L.DomUtil and setTransform,i post the code below if it can help anyone. I precise i wanted to transform the icon on popupopen event.
private zoomIconOnPopupOpen(scale): void {
this.map.on('popupopen', (event1: any) => {
let marker = event1.popup._source;
if (marker._icon) {
const pos = L.DomUtil.getPosition(marker._icon);
L.DomUtil.setTransform(marker._icon, pos, scale);
}
});
this.map.on('popupclose', (event1: any) => {
let marker = event1.popup._source;
if (marker._icon) {
const pos = L.DomUtil.getPosition(marker._icon);
L.DomUtil.setTransform(marker._icon, pos, 1);
}
});
}
I'm trying to change the default marker for one of my KML layers. I'm using leaflet-omnivore for this.
This is the code I already have. The markers are not changing to the image and the layer control is only displaying the text, even though the img bit is in the code.
Marker Code:
var redIcon = L.icon({
iconUrl: 'icon.png',
iconSize: [20, 24],
iconAnchor: [12, 55],
popupAnchor: [-3, -76]
});
var nissanLayer = omnivore.kml('icons.kml')
.on('ready', function() {
map.fitBounds(customLayer.getBounds());
//change the icons for each point on the map
// After the 'ready' event fires, the GeoJSON contents are accessible
// and you can iterate through layers to bind custom popups.
customLayer.eachLayer(function(layer) {
// See the `.bindPopup` documentation for full details. This
// dataset has a property called `name`: your dataset might not,
// so inspect it and customize to taste.
layer.icon
layer.bindPopup('<img src="icon.png" height="24"><br><h3>'+layer.feature.properties.name+'</h3>');
});
})
.addTo(map);
var marker = new L.Marker(customLayer, {icon:redIcon});
map.addLayer(marker);
You seem to have overlooked the setIcon() method of L.Marker. I'd also check that a L.Layer is in fact a L.Marker before calling any L.Marker functionality, just for code sanity. e.g.:
var redIcon = L.icon({ /* ... */ });
var omnivoreLayer = omnivore.kml('icons.kml')
.on('ready', function() {
omnivoreLayer.eachLayer(function(layer) {
if (layer instanceof L.Marker) {
layer.setIcon(redIcon);
}
});
})
.addTo(map);
However, the Leaflet-Omnivore documentation says that the better way to apply custom styling to an Omnivore layer is to create a L.GeoJSON instance with the desired filters and styling, and then pass that to the Omnivore factory method. I suggest you read the Leaflet tutorial on GeoJSON to become familiar with this.
So instead of relying on a on('ready') event handler (which would change the markers after they are created), this would save a tiny bit of time by creating the markers directly with the desired style:
var omnivoreStyleHelper = L.geoJSON(null, {
pointToLayer: function (feature, latlng) {
return L.marker(latlng, {icon: redIcon});
}
});
var omnivoreLayer = omnivore.kml('icons.kml', null, omnivoreStyleHelper);
I haven't used leaflet that much but I did a small project where I set the icons to an image.
var redIcon = L.icon({
iconUrl: 'red-x.png',
iconSize: [25, 25], // size of the icon
iconAnchor: [12, 55], // point of the icon which will correspond to
marker's location
popupAnchor: [-3, -76] // point from which the popup should open
relative to the iconAnchor
});
var marker = new L.Marker(markerLocation, {icon:redIcon});
mymap.addLayer(marker);
Not sure how helpful this is really.
Links got a guide to follow which might be more use https://leafletjs.com/examples/custom-icons/
I am using leaflet to plot a series of polylines. For each polyline, I have want a custom pop up which presents an image. I have managed to achieve this functionality for a single polyline and now wish to generate this functionality for a series of polylines, read from a json file.
var map = L.map('map', {scrollWheelZoom:false}).setView([25.198696, 55.269794], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
var random_icon = L.icon({
iconUrl: 'https://cdn4.iconfinder.com/data/icons/defaulticon/icons/png/256x256/media-shuffle.png',
iconSize: [38, 95], // size of the icon
popupAnchor: [0,-15]
});
var customPopup = "test image<br/><img src='http://i.imgur.com/NpZuKvK.png' alt='maptime logo gif' width='350px'/>";
var customOptions =
{
'maxWidth': '500',
'className' : 'custom'
}
var pointA = new L.LatLng(25.146619, 55.225746);
var pointB = new L.LatLng(25.198696, 55.269794);
var pointList = [pointA,pointB];
L.polyline(pointList,{icon: random_icon,color:'red','weight':10}).bindPopup(customPopup,customOptions).addTo(map);
This presents a polyline which when clicked on, presents the image from imgur.
I have now created a geojson file which I've added here.
How do I got about a.loading this geojson file b. iterating through it and creating the following var's : customPopup with the url from the geojson, the pointList and points from the geojson file and finally render the polyline?
I agree with ghybs, the answer is in the documentation of Leaflet.
First, you need to get the GeoJson content by an Ajax request or whatever you want. Then, simply use L.geoJson options. Here is more or less what you need (it uses JQuery) :
function genPopup(url, name){
return name + '<br/><img src="' + url + '" alt="maptime logo gif" width="350px"/>';
}
$.get('https://gist.github.com/gac55/52ab01944be1e39e154cd2a5709de737', function (data){
var jsondata = $.parseJSON(data);
L.geoJson(jsondata, {
color: 'red',
weight: 10,
onEachFeature: function(feature, layer){
var furl = feature.properties.url;
var fname = feature.properties.name;
layer.bindPopup(
genPopup(furl, fname),
customOptions
);
}
}).addTo(map);
});
I am using the Leaflet.Awesome-Markers plugin with LeafletJS.
I have implemented it correctly, however now I'd like to be able to use numbers from 0 - 9 to represent markers.
Here's a JS Fiddle implementation to show how the plugin behaves.
http://jsfiddle.net/fulvio/VPzu4/200/
The plugin allows the use of font-awesome icons and glyph icons (both of course, do not offer any 0 - 9 numbers as icons. argh!)
http://getbootstrap.com/components/#glyphicons
http://fortawesome.github.io/Font-Awesome/cheatsheet/
The documentation mentions the ability to use extraClasses and I was wondering whether anyone could point me in the right direction as to how to leverage from this in order to display numbers rather than icons or whether there is simply another way to achieve this.
Thanks in advance for your help.
UPDATE:
Thanks for the comment #Can.
The author of awesome-markers got another tree where he added exactly what you are looking for awesome-markers with numbers/letters be sure to grab the unminified JS.
I have tried Numbered Markers plugin, but it icon is not pretty as other Awesome Markers, and make page layout style inconsistent, so I made small changes in Awesome-Markers plugin to make it support numbers. It is very simple.
this is Numbered Markers plugin effect, if you like it please skip my answer.
change leaflet.awesome-markers.js line 2, add html:""
L.AwesomeMarkers.Icon = L.Icon.extend({
options: {
iconSize: [35, 45],
iconAnchor: [17, 42],
popupAnchor: [1, -32],
shadowAnchor: [10, 12],
shadowSize: [36, 16],
className: 'awesome-marker',
prefix: 'glyphicon',
spinClass: 'fa-spin',
extraClasses: '',
icon: 'home',
markerColor: 'blue',
iconColor: 'white',
html : ""
},
change leaflet.awesome-markers.js line 80,
return "<i " + iconColorStyle + "class='" + options.extraClasses + " "
+ options.prefix + " " + iconClass + " " + iconSpinClass + " "
+ iconColorClass + "'>" + options.html + "</i>";
when creating icon, call like before
var jobMarkerIcon = L.AwesomeMarkers.icon({
icon: '',
markerColor: 'darkblue',
prefix: 'fa',
html: (i+1)
});
comment out line 45 and 47.
the result is like below screenshot.
code changes diff shows below.
Instead of using the Awesome-Markers plugin, you could follow this article on creating numbered markers in Leaflet:
http://blog.charliecroom.com/index.php/web/numbered-markers-in-leaflet
The associated Gist is here:
https://gist.github.com/comp615/2288108
An simple example of how this would work is as follows:
// The text could also be letters instead of numbers if that's more appropriate
var marker = new L.Marker(new L.LatLng(0, 0), {
icon: new L.NumberedDivIcon({number: '1'})
});
Another strategy is to use the Leaflet.ExtraMarkers plugin
Code the numeric marker with these options:
var numMarker = L.ExtraMarkers.icon({
icon: 'fa-number',
number: 12,
markerColor: 'blue'
});
L.marker([41.77, -72.69], {icon: numMarker}).addTo(map);
If you don't want to use the font-awesome, a fairly simple solution presented here:
Simple Numbered Markers
it doesn't need any extra library. It's already in leaflet. Just create a CSS class with icon image like this:
.number-icon
{
background-image: url("images/number-marker-icon.png");
background-size: 40px 40px;
background-repeat: no-repeat;
margin: 0 auto;
text-align:center;
color:white;
font-weight: bold;
}
Then create icon like this:
var numberIcon = L.divIcon({
className: "number-icon",
shadowSize: [20, 30], // size of the shadow
iconAnchor: [20, 40],
shadowAnchor: [4, 30], // the same for the shadow
popupAnchor: [0, -30],
html: variable_containing_the_number
});
var marker = new L.marker([lat, long],
{
icon: numberIcon
});