React-Leaflet rotate icon - react-leaflet

In my old leaflet application I used this code to rotate an icon and it worked perfectly.
Now, I'm trying to move the code to react-leaflet but cannot figure out how to apply this.
I know it should be possible via custom components, I tried to create some kind on RotatedMarker (based on Marker.js in the src), but as I'm new to all that, I could not make it work...
Can anyone point me in the right direction?
Thanks,
Alex

Ok. This is what I did to make it work. Not sure it should be done this way, but it seems to work.
export default class RotatedMarker extends Marker {
componentDidMount() {
super.componentDidMount();
this.leafletElement.setIconAngle(this.props.rotation);
}
componentWillUpdate(nextProps, nextState) {
if (nextProps.rotation) {
this.leafletElement.setIconAngle(nextProps.rotation);
}
}
}

I found another way, try constructing the icon like this:
var icon = L.divIcon({
iconSize: [20, 20],
iconAnchor: [10, 10],
className: 'yourClassName',
html: `<img
style="transform: rotate(80deg);"
height="20"
width="20"
src='path/to/icon'>`
})
And then add it to your marker:
<Marker position={position} icon={icon} />

Related

Style layer.editing in leaflet

I'm working on getting the events of deletion and edition outside the box of leaflet, meaning using buttons binded to events instead of the drawtoolbar.
The editing button calls layer.editing.enable();
What I've done earlier is style the polygones under editition mode using an extend of the class Edit:
L.Edit.PolyVerticesEdit = L.Edit.PolyVerticesEdit.extend({
options: {
icon: new L.DivIcon({
className: 'edit-marker',
iconSize: [28, 28],
html: '<i class="fa fa-circle fa-2x fa-circle"></i>'
})
}
});
So, when I do an edit using the drawtoolbar, the shapes are styled correctly. However, when I use the button( layer.editing.enable()) the shapes are under default styles. So my conclusion was that draw Toolbar doesn't class the same method as layer.editing.enable(); from here comes my question.
How can I style the polygon vertices using layer.editing.enable() ?
Case of using buttons
case of using toolbar

Mapbox Directions configure markers

I'm using the Mapbox directions API and leaflet to create an interactive map.
When invoking the directions functionality, everything works great and Mapbox sets a marker for my origin and destination.
By default, it uses a generic marker with A and B respectively. I can't find any documentation on configuring the marker it uses, does anyone have any insights, examples, or suggestions?
Thank you!
The documentation seems to focus on featureLayers to make custom pin. I found that markers with custom icon do the job better.
Here is the way I do it:
blueIcon = new L.icon({
iconUrl: '/img/Bo6.png',
iconSize: [75, 75], // size of the icon
popupAnchor: [300, -125]
});
movingMarker = new L.marker([51.5, -54.11],
{
"title": "Felix in Space",
"description": "1718 14th St NW, Washington, DC",
className: "event-popup-box",
icon: blueIcon
});
movingMarker.addTo(themap);

Leaflet: How to add a text label to a custom marker icon?

Is it possible to add text to a custom icon marker? I want to avoid having to edit the icon in an image editor just to add the text.
I've created my custom icon marker like so:
var airfieldIcon = L.icon({
iconUrl: 'images/airfield.png',
iconSize: [48,48]
});
var airfield = L.geoJson (airfield, {
pointToLayer: function(feature,latlng){
return L.marker(latlng, {
icon: airfieldIcon
})
}
}).addTo(map);
How would I add the text "Banff Airfield" as a label to this icon? Is the easiest and most efficient way through using an image editor? if so, I will do that method, but wondering if there was a better way. Thanks!
You could use a L.DivIcon:
Represents a lightweight icon for markers that uses a simple div element instead of an image.
http://leafletjs.com/reference.html#divicon
Put your image and text in it's HTML, sprinkle some CSS to make it appear the way you want and you're good to go
new L.Marker([57.666667, -2.64], {
icon: new L.DivIcon({
className: 'my-div-icon',
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>'
})
});
Another option is to use the Leaflet.Label plugin:
Leaflet.label is plugin for adding labels to markers & shapes on leaflet powered maps.
Repository: https://github.com/Leaflet/Leaflet.label
Example: http://leaflet.github.io/Leaflet.label/
As of leaflet version 1.0.0, you can add a label without using a plugin (the plugin has been rolled into the core functionality).
Example:
var marker = L.marker(latlng)
.bindTooltip("Test Label",
{
permanent: true,
direction: 'right'
}
);
This yields a marker on the map with a label of "Test Label" which is always displayed to the right of the marker's icon.
To further explore Mark's answer, if you want to know an easy way to add text (number) over a marker like this:
You just have to proceed as follows:
1. Instantiate an icon (map.js)
var stepIcon = L.icon({
iconUrl: 'graphic/yellow-circle.png', // the background image you want
iconSize: [40, 40], // size of the icon
});
2.1 Setting the icon (map.js)
var marker = new L.marker([39.5, 77.3], { icon:stepIcon});
marker.bindTooltip("12" //specific number, {
permanent: true,
direction: 'center',
className: "my-labels"
});
marker.addTo(map);
2.2 Setting the icon (map.css)
.leaflet-tooltip.my-labels {
background-color: transparent;
border: transparent;
box-shadow: none;
font-weight: bold;
font-size: 30px;
}
Make sure you have imported your .css file into your .html page.
this is out of box solution it may not suitable for everyone but it works for me
simply you can add marker of icon then marker of text Like this :
var MarkerIcon = L.icon(feature.geometry.properties.icon);
var MarkerText = L.divIcon(
{className: TextPositionClass,
html:'<div>'+ displayText+'</div>',
iconSize: null
});
let marker = L.marker(latlng, {icon: MarkerIcon}).addTo(this.map); // add marker
let label = L.marker(latlng, {icon: MarkerText}).addTo(this.map); // add text on marker

How to apply css on polylines : leaflet

I am working with the application which uses leaflet api.
Introduction
I needed to draw different types of fences, using decorators i can somewhat apply good visuals to the polylines but not much.
Problem
I was willing to show twisted wires instead of dashes, dots or plain lines and I know the twisted wire line will be an image but can't find help about applying custom css to polylines.
Script Example
var fence2Icon = L.icon({
iconUrl: 'xxxx.png',
iconSize: [5, 20]
iconAnchor: [5, 18]
});
// Add coordinate to the polyline
var polylineFence2 = new L.Polyline([], { color: 'red' });
function fencePlace2(e) {
// New marker on coordinate, add it to the map
new L.Marker(e.latlng, { icon: fence2Icon, draggable: false }).addTo(curr);
// Add coordinate to the polyline
polylineFence2.addLatLng(e.latlng).addTo(curr);
var decorator = L.polylineDecorator(polylineFence2, {
patterns:[{offset:5,repeat:'20px',symbol:new L.Symbol.Dash({pixelSize:5})
}]
}).addTo(curr);
}
L.easyButton('fa-flash', function () {
$('.leaflet-container').css('cursor', 'crosshair');
map.on('click', fencePlace2);
polylineFence2 = new L.Polyline([], { color: 'red' });
}).addTo(map);
If someone know anything about polyline or another way please do help.
Thanks for your time:-)
You can add a class in the options of your polyline ...
var polyline = L.polyline(latlngs, { className: 'my_polyline' }).addTo(map);
and add your own settings in the CSS ...
.my_polyline {
stroke: green;
fill: none;
stroke-dasharray: 10,10;
stroke-width: 5;
}
Here is an example: http://jsfiddle.net/FranceImage/9dggfhnc/
You can also access some options directly ...
var polyline = L.polyline(latlngs, { dashArray: '10,10' }).addTo(map);
See Path Options
If you create a polyline you're in fact adding an element to the SVG element which Leaflet uses to draw it's overlays. Styling SVG path elements is different from styling regular HTML elements. There's no such thing as border and background-color etc. It has different properties, if you're interested here's a nice read on the matter:
https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Fills_and_Strokes
You can style Leaflet's path elements when you instanciate them via options or via CSS using the properties (related to styling) described in the documentation here:
http://leafletjs.com/reference.html#path
Via options:
new L.Polyline([...], {
weight: 3,
color: 'red',
opacity: 0.5
}).addTo(map);
Via CSS:
new L.Polyline([...], {
className: 'polyline'
}).addTo(map);
.polyline {
weight: 3,
color: red,
opacity: 0.5
}
However, what you want, using an image simply isn't possible. You can use images as fill for SVG paths, but it would be impossible for your usecase. You'de need to add a pattern definition to the SVG Leaflet is using and then you could use that id as the fill property as outlined in this answer:
https://stackoverflow.com/a/3798797/2019281 but will always fill/tile the image horizontally which won't work if your polyline is vertical.

How do you change the offset for a leaflet popup using angular leaflet directive and geojson?

I'm using the angular-leaflet-directive and geojson to create map markers using leaflet and mapbox. The popups on the markers aren't correctly aligned on the marker.
angular.extend($scope, { // Map data
geojson: {
data: $scope.filteredShows,
onEachFeature: function (feature, layer) {
layer.bindPopup(feature.properties.artist + ' ยท ' + feature.properties.venue);
layer.setIcon(defaultMarker);
layer.on({
mouseover: pointMouseover,
mouseout: pointMouseout
});
layers[feature.properties.id] = layer;
}
}
});
How do I change the offset on the markers?
Using popupAnchor: [-10, -10], in L.Icon. See http://leafletjs.com/reference.html#icon
If you're using the default images, but they're placed at a different location with different filenames because you're using a Rails server to serve the assets, for example, here's a tip so you don't have to hard code in the values from the default icon.
In my case, I injected the actual values into the proper location.
<script type="text/javascript">
var injectedData = {
paths: {
leafletIcon: {
iconRetinaUrl: '<%= image_url "leaflet-1.3.4/marker-icon-2x.png" %>',
iconUrl: '<%= image_url "leaflet-1.3.4/marker-icon.png" %>',
shadowUrl: '<%= image_url "leaflet-1.3.4/marker-shadow.png" %>',
},
},
};
</script>
Then, I created an instance of Icon that uses the default values for image offsets directly from the Icon.Default prototype.
import { Icon } from 'leaflet';
const defaultIcon = new Icon({
...Icon.Default.prototype.options,
...injectedData.paths.leafletIcon,
});
That's the same as injecting your data directly. Do as is appropriate for your particular use case.
const defaultIcon = new Icon({
...Icon.Default.prototype.options,
{
iconRetinaUrl: "/assets/leaflet-1.3.4/marker-icon-2x-00179c4c1ee830d3a108412ae0d294f55776cfeb085c60129a39aa6fc4ae2528.png",
iconUrl: "/assets/leaflet-1.3.4/marker-icon-574c3a5cca85f4114085b6841596d62f00d7c892c7b03f28cbfa301deb1dc437.png",
shadowUrl: "/assets/leaflet-1.3.4/marker-shadow-264f5c640339f042dd729062cfc04c17f8ea0f29882b538e3848ed8f10edb4da.png",
},
});
In my case, I was using the react-leaflet library with React, not Angular, but I'm sure you can adapt your use-case appropriately. In my case, I used the defaultIcon as a prop for the Marker component.
<Map center={position} zoom={zoom}>
<TileLayer
attribution='&copy OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker icon={defaultIcon} position={position}>
<Popup>
<span>{this.props.location}</span>
</Popup>
</Marker>
</Map>
I know this doesn't answer your question directly, but your question and vitalik_74's answer got me on the road to what I needed for my particular use-case, which was an easy but reliable way to provide different image URLs for the default icon set (including altered filenames) while also reusing the default offset numbers without having to hard code them in. I hope my answer can help someone else who comes across this question with this issue in the future.