Custom Markers for v-leaflet

Hello all,

fiddling around with v-leaflet as unfortunately the google maps add-on does not work in China.

I liked v-leaflet a lot and I am trying to figure out how to create a custom marker.

I managed to show my own png files as markers, however I am trying to make use of the .setDivIcon method that takes a String as an argument.

If I set some html in there (like the example in Matti’s github https://github.com/mstahv/v-leaflet/blob/master/src/test/java/org/vaadin/addon/leaflet/demoandtestapp/TextOnMap.java ) I get the text and a white square next to it. Why is that?

I also checked the code in the connector and I saw that you use some SVG path to create the marker icon around FontAwesome icons.

I would love to use my own SVG paths (as I did with Google Maps using their Symbol class) - Is that possible? Would I have to clone the add-ons code into my project and modify its client side and the connector in order to support that?

Last but not least. What about rotating markers?

Best regards and thanks for the amazing add-on.

George

Hi,

Oh, lots of questions :slight_smile: Can’t answer all directly, should check some things.

Don’t remember the white square thing, might be a regression. If you think it is a bug as well, create an issue about it to github project page.

IIRC Leaflet 1.0 now contains a better way to put raw text on a map, should see if I could upgrade that example a bit.

Can’t remember how SVG icon/fontawesome thing works, could look at it soon, should look into updating to leaflet 1.0 final first.
For rotated markers, there is a GWT add-on, but its author hasn’t created a Vaadin version, I guess creating that shouldn’t be that difficult:
https://vaadin.com/directory#!addon/g-leaflet-rotatedmarker

For rotating, I guess you could use some CSS magic as well…

cheers,
matti

I checked into teh white quare thing you mentioned. I guess you need to explicitly define the size, otherwise it will end up being some minimum size → small square. In the example I seem to use this kind of code:

    LMarker m = new LMarker(0,0);
    m.setDivIcon("Hello <strong>world</strong>!");
    // define the size for the html box
    m.setIconSize(new Point(80,20));
    leafletMap.addLayer(m);

I guess Leaflet needs the size to properly position the divIcon. If you don’t want to show the background and border, you can probably just us CSS to get rid of that.

cheers,
matti

Hello again Matti,

I now looked into your code here:
https://github.com/mstahv/v-leaflet/blob/b84cd4b1d94e4e01297231b2a60381817eb48034/src/main/java/org/vaadin/addon/leaflet/client/LeafletMarkerConnector.java

and I see that I can create a divIcon using custom svg as you do for fontawesome

for custom divIcon

else if (divIcon != null) {
DivIconOptions divIconOptions = DivIconOptions.create();
configureIconSize(divIconOptions);
if (ComponentStateUtil.hasStyles(getState())) {
StringBuilder builder = new StringBuilder();
for (String style : getState().styles) {
builder.append(style).append(" ");
}
divIconOptions.setClassName(builder.toString());
}
divIconOptions.setHtml(divIcon);
DivIcon icon = DivIcon.create(divIconOptions);
options.setIcon(icon);
}

and for fontawesome

if (urlReference != null && urlReference.getURL().startsWith("fonticon://")) {
// fonticons have special handling
com.vaadin.client.ui.Icon vIcon = getIcon();
String fontAwesomeChar = vIcon.getElement().getInnerText();
StringBuilder svgSb = new StringBuilder();
// TODO make this configurable, consider making also possible to
// use configurable SVG marker without fontawesome icon in marker
svgSb.append("<svg width=\"25px\" height=\"40px\"><path fill=\"#44AEEA\" stroke=\"#005FA8\" d=\"M12.544,0.5C5.971,0.5,0.5,6.24,0.5,12.416c0,2.777,1.564,6.308,2.694,8.745\n"
+ "L12.5,38.922l9.262-17.761c1.13-2.438,2.738-5.791,2.738-8.745C24.5,6.24,19.117,0.5,12.544,0.5L12.544,0.5z\"/><text fill=\"#fff\" x=\"12.5\" y=\"20\" text-anchor=\"middle\" font-size=\"16\" class=\"");
svgSb.append(vIcon.getStyleName());
svgSb.append("\">");
svgSb.append(fontAwesomeChar);
svgSb.append("</text></svg>");
DivIconOptions divIconOptions = DivIconOptions.create();
divIconOptions.setClassName("v-leaflet-custom-svg");
divIconOptions.setHtml(svgSb.toString());
divIconOptions.setIconSize(Point.create(25, 40));
divIconOptions.setIconAnchor(Point.create(12.5, 40));
configureIconSize(divIconOptions);
DivIcon icon = DivIcon.create(divIconOptions);
options.setIcon(icon);
}

Could you please explain what class name “v-leaflet-custom-svg” is and where can I define mine in order to use my own svg path?

best regards,
George

Hello,

to answer my own question.

The add-on is currently capable of displaying custom Markers (using SVG code).

To do so one must do:

        LMarker marker = new LMarker();
        String svgCode = "<svg>your svg code here</svg>";
        marker.addStyleName("v-leaflet-custom-svg");
        marker.setDivIcon(svgCode);

Matti, if you could add this as an example on the add-on page or something for other people to find.

Regards,
George

Does anybody knows why rotated marker icon is not where it should be on a map? It’s always moved for some distance from it should be on a map. Only when make max zoom in it’s where it should be?

Is the Marker size and anchor point specified correctly? If those are, then it is probably an issue in the underlaying JS library.

cheers,
matti

I didn’t specified anything, how to do that? I want to set middle of icon marker on location coordinates

Try with setIconSize and setIconAnchor:

https://github.com/mstahv/v-leaflet/blob/master/src/main/java/org/vaadin/addon/leaflet/LMarker.java#L74

Thanks, I will check that

setIconSize resolve this, thanks again

Hi Matti,
is there a possibility to simply change the color of the marker? The setStyle()-Method doesn’t seem to do anything.
I just need to change the default color of the icon to e.g. red, green etc. The svg can stay unchanged.
Thanks!

The default marker is a raster image IIRC. It might be quite easy to make the color of SVG marker to be configured somehow. Do you have a static list of colors you’d use or would those need to be dynamic? If static, then the solution could use CSS.

cheers,
matti

Hi Matti,
static would be totally sufficient. It should be enough to have something like let’s say 10 or 20 predefined colors to play with. I tried with CSS, but no luck.
Can you provide an example pls?
Thanks

Hello,

you can use any colour you like if you use an SVG marker.

 LMarker marker = new LMarker();
 String svgCode = "<svg>your svg code here</svg>";
 marker.addStyleName("v-leaflet-custom-svg");
 marker.setDivIcon(svgCode);

You just need to specify the color in your SVG code / path

Works like a charm! Thanks George!

I’m finding that if I put setIconSize(…) the whole background of the icon will be a white box. If I leave it then I still get a whitebox but it’s much smaller. setIconAnchor only seems to adjust where the anchor is and has no bearing on the whitebox (whether you set it or not). As in has the fix changed over the last year?

Stephan, do you need that whitebox or not? I think most often you want to get rid of it using the v-leaflet-custom-svg stylename. If you need to block transparency, you can do that in the image/svg.

cheers,
matti

hello all,
I use v-leaflet to create my map in a web application i create many markers with different icon
I need to create a click listener on a marker and open a pop up window
Can you provide an example please?
Thanks

Hi toufichamoud!

I the custom markers thing is discussed in this thread and in the examples is projects github repository (in src/test/java).

Here is how to open a popup window from a click to marker:

	LMap map = new LMap();
	map.addLayer(new LOpenStreetMapLayer());
	setContent(map);
	LMarker marker = new LMarker(0,0);
	marker.addClickListener( e -> {
		Window w = new Window("My new window");
		w.setModal(true);
		w.setContent(new Label("Window content"));
		getUI().addWindow(w);
	});
	map.addLayer(marker);