Using Leaflet.AwesomeMarkers plugin with Font Awesome 5? - leaflet

How do I upgrade to Font Awesome 5 for the leaflet plugin Leaflet.awesome-markers? This plugin has not been updated on github for some time and uses font awesome v4.
This is for an app that uses mapbox, leaflet and leaflet awesome markers with font awesome v4 and works correctly.
I've tried to upgrade to Font Awesome 5 like so:
app.scss
#import url('webfonts/font-awesome-pro-5.0.1.css');
#import url('webfonts/fa-solid-900.ttf');
#import url('webfonts/fa-solid-900.woff');
#import url('webfonts/fa-solid-900.woff2');
#import url('webfonts/fa-regular-400.ttf');
#import url('webfonts/fa-regular-400.woff');
#import url('webfonts/fa-regular-400.woff2');
And index.html:
<script src="scripts/fontawesome-all-5.0.1.min.js"></script>
After upgrading to Font Awesome 5, the leaflet markers are displaying with the icons too small, and not in the center of the marker. They were correct with v4.
I found this possible fix, but it made no difference, the icons are still too small and not centered: https://gist.github.com/pikesley/0197f9ea8aff737e6b80c945f741d584
var marker = L.AwesomeMarkers.icon({
markerColor: 'blue',
prefix: 'fa',
extraClasses: 'fas',
icon: 'music'
});
How can I fix this for Font Awesome 5?

As suggested by #mwilkerson's answer, your current code mixes the JS and Webfonts CSS approaches of Font Awesome 5. Only one approach is necessary.
Webfonts CSS:
The Webfonts Font Awesome 5 approach seems to work fine with the (no longer maintained) plugin
lvoogdt/Leaflet.awesome-markers version 2.0.2:
(here using the 'arrow-alt-circle-down' icon to show that it is correctly centered, because the 'music' one is very asymmetric)
var paris = [48.86, 2.35];
var map = L.map('map').setView(paris, 11);
var marker = L.AwesomeMarkers.icon({
markerColor: 'blue',
prefix: 'fa',
extraClasses: 'fas',
icon: 'arrow-alt-circle-down' //'music'
});
L.marker(paris, {
icon: marker,
}).addTo(map);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/leaflet#1.3.1/dist/leaflet-src.js" integrity="sha512-IkGU/uDhB9u9F8k+2OsA6XXoowIhOuQL1NTgNZHY1nkURnqEGlDZq3GsfmdJdKFe1k1zOc6YU2K7qY+hF9AodA==" crossorigin=""></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/lvoogdt/Leaflet.awesome-markers#2.0.2/dist/leaflet.awesome-markers.css" />
<script src="https://cdn.jsdelivr.net/gh/lvoogdt/Leaflet.awesome-markers#2.0.2/dist/leaflet.awesome-markers.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" integrity="sha384-DNOHZ68U8hZfKXOrtjWvjxusGo9WQnrNx2sqG0tfsghAvtVlRW3tvkXWZh58N9jp" crossorigin="anonymous">
<div id="map" style="height: 180px"></div>
JS approach:
The JS Font Awesome 5 approach dynamically replaces the <i> element by an <svg>, therefore it is no longer styled by the plugin CSS.
You can easily restore this styling by duplicating the CSS rule:
.awesome-marker svg {
color: #333;
margin-top: 10px;
display: inline-block;
font-size: 14px;
}
var paris = [48.86, 2.35];
var map = L.map('map').setView(paris, 11);
var marker = L.AwesomeMarkers.icon({
markerColor: 'blue',
prefix: 'fa',
extraClasses: 'fas',
icon: 'arrow-alt-circle-down' //'music'
});
L.marker(paris, {
icon: marker,
}).addTo(map);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
.awesome-marker svg {
color: #333;
margin-top: 10px;
display: inline-block;
font-size: 14px;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/leaflet#1.3.1/dist/leaflet-src.js" integrity="sha512-IkGU/uDhB9u9F8k+2OsA6XXoowIhOuQL1NTgNZHY1nkURnqEGlDZq3GsfmdJdKFe1k1zOc6YU2K7qY+hF9AodA==" crossorigin=""></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/lvoogdt/Leaflet.awesome-markers#2.0.2/dist/leaflet.awesome-markers.css" />
<script src="https://cdn.jsdelivr.net/gh/lvoogdt/Leaflet.awesome-markers#2.0.2/dist/leaflet.awesome-markers.js"></script>
<script defer src="https://use.fontawesome.com/releases/v5.0.13/js/all.js" integrity="sha384-xymdQtn1n3lH2wcu0qhcdaOpQwyoarkgLVxC/wZ5q7h9gHtxICrpcaSUfygqZGOe" crossorigin="anonymous"></script>
<div id="map" style="height: 180px"></div>

The first step I'd take in resolving this is to determine whether you need to be using the Webfonts with CSS method for Font Awesome 5, or the SVG with JavaScript method, and then focus on that one, removing the other.
In your example code, you are loading both: Webfonts in your app.scss and SVG/JS in your index.html with the <script> block.
Perhaps resolving that set up issue will solve the whole problem. Or at least, it will help clear things up to identify and troubleshoot any remaining issue.
I would recommend starting with the Webfonts approach, to see if you can get that working. If so, then just remove that <script> block from index.html.
However, there are several common issues around upgrading from v4 to v5 (see notes on upgrading here). One of those issues has to do with the names of some icons changing between these major versions (the linked upgrade doc lists the specific icon names that have changed). There is a v4 shim that can ease the upgrade process by automatically translating any v4-only icon names to their v5 counterparts. But this v4 shim only works with the SVG with JavaScript method (details on that same linked upgrade doc). So if you need to use that v4 shim, then you'll need focus on the SVG with JavaScript method and drop the webfont loading in your app.scss.

steps to implement awesome icons into the map:
add this link to the index.html file(root file) if the app
<script src="https://cdn.jsdelivr.net/gh/lvoogdt/Leaflet.awesome-markers#2.0.2/dist/leaflet.awesome-markers.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/lvoogdt/Leaflet.awesome-markers#2.0.2/dist/leaflet.awesome-markers.css"/>
add this variable
var marker = leaflet.AwesomeMarkers.icon({
icon: 'arrow-alt-circle-down', //'music'
markerColor: 'blue',
prefix: ' fa fa-fa fa-paint-brush',
});
List item
attach the icon to the marker
leaflet.marker([property.lat, property.long], {
icon: marker
})

Related

Angular 13 Leaflet Will Not Render Map Correctly

I am having an issue where when I attempt to render a map using Leaflet in Angular 13, I am getting the following...
I have the leaflet.css and styles.css loaded in the angular.json file...
"styles": ["src/styles.scss",
"node_modules/leaflet/dist/leaflet.css"]
I have the leaflet.css and styles.css loaded in the app.component.ts...
styleUrls: ['./on-site-proctor-locator.component.scss',
'../../../../../node_modules/leaflet/dist/leaflet.css']
In the app.component.ts file, here is where I initialize the map...
this.map = L.map('map').setView([ lat, lon ], zoom);
const tiles = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 20,
attribution: '© Stadia Maps, © OpenMapTiles' +
'© OpenStreetMap contributors'
});
tiles.addTo(this.map);
Here is what I have setup in the app.component.html file for the div...
<div id="map" class="map-div"></div>
I have looked at other posts of similar struggles and have found nothing that has helped me. I would appreciate any suggestions on what I can do to resolve this issue. Thank you.
this is what worked for me (angular 14 project+leaflet 1.8):
on this line
<div id="map" class="map-div"></div>
add a width and height, to read something like this
<div id="map" class="map-div" style="width: 100%; height: 300px"></div>
leaflet requires the container to be visible, and have a reference width/height in order to render correctly.
I hope it helps

problem with leaflet in a smarty template

I'm using SmartyBC on version 3.1.33. In the smarty template the code of leaflet and openstreetmap will not run. The map will not open.
I've all tested with or without the script between {literal} {/literal}. The map will not open. However, in a normally html site the code works perfectly. What's the mistake?
<html>
<head><link rel="stylesheet" type="text/css" href="https://unpkg.com/leaflet#1.5.1/dist/leaflet.css">
<script src='https://unpkg.com/leaflet#1.5.1/dist/leaflet.js'></script>
#map {
height: 500px;
}
</head>
<body>
<div id="map"></div>
<script>
{literal}
var map = L.map('map').setView([43.64701, -79.39425], 15);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
L.marker([51.5, -0.09]).addTo(map)
.bindPopup('A pretty CSS3 popup.<br> Easily customizable.')
.openPopup();
{/literal}
</script>
</body>
</html>
No error messages and no map. Thanks for help.
You didn't put #map styles in HTML <style>. I did that and the same code without {literal} tags worked.
https://codepen.io/anon/pen/vqVLjL

ArcGis layers on mapbox gl

I'm trying to add a layer from an api on ArcGis:
https://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Facility_and_Structure/MapServer/1
In leaflet it is posible with:
L.esri.featureLayer({
url:"https://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Facility_and_Structure/MapServer/1",
style: function () {
return { color: "#70ca49", weight: 2 };
}
}).addTo(map);
Is there a way to do this on mapboxgl?
Hi Jorge Monroy - Mapbox GL JS expects the data sources as such. In your case where you're wanting to load building footprints from an ArcGIS REST Service, your best bet is to load them as a geojson.
It looks like you're publishing the services from ArcServer 10.31. In that case, the way that I've loaded ArcGIS REST services is by exposing them through AGOL as explained there. If you have that option, that seems easiest. Otherwise, there are other (work-arounds)[https://gis.stackexchange.com/questions/13029/converting-arcgis-server-json-to-geojson] that I've no experience with.
Using Washington D.C. as an example, if you navigate to: http://opendata.dc.gov/datasets/building-footprints and then click on APIs, you can copy the link to the geojson service.
You can then load into MapboxGL JS through the data property of the geojson source shown there.
You can use leaflet-mapbox-gl.js to integrate leaflet and mapbox. Get token from mapbox and add it to below example to make it work.
References: https://github.com/mapbox/mapbox-gl-leaflet
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css"/>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.css' rel='stylesheet' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.js'></script>
<script src="https://unpkg.com/mapbox-gl-leaflet/leaflet-mapbox-gl.js"></script>
<script src="https://unpkg.com/esri-leaflet/dist/esri-leaflet.js"></script>
<style>
html, body, #map {
margin:0; padding:0; width : 100%; height : 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
var token = "";//add token before running this example
const INITIAL_VIEW_STATE = {
latitude: 45.528,
longitude: -122.680,
zoom: 13
};
var map = L.map('map').setView([45.528, -122.680], 13);
L.esri.basemapLayer("NationalGeographic").addTo(map);
var parks = L.esri.featureLayer({
url: "https://services.arcgis.com/rOo16HdIMeOBI4Mb/arcgis/rest/services/Portland_Parks/FeatureServer/0",
style: function () {
return { color: "#70ca49", weight: 2 };
}
}).addTo(map);
var gl = L.mapboxGL({
accessToken: token,
style: 'mapbox://styles/mapbox/dark-v10'
}).addTo(map);
//To add anything on mapbox, first access the mapbox using getMapboxMap()
gl.getMapboxMap().on('load', () => {
//To load any layer on mapbox
//gl.getMapboxMap().addLayer();
});
var popupTemplate = "<h3>{NAME}</h3>{ACRES} Acres<br><small>Property ID: {PROPERTYID}<small>";
parks.bindPopup(function(e){
return L.Util.template(popupTemplate, e.feature.properties)
});
</script>
</body>
</html>

Leaflet breaks on load

I am facing issue with leaflet library. When I try to load map, images are loaded more then once. I am using leaflet with angular, grunt and browserify. I suspect it can be because of order of loading libraries and async execution, but I am not sure. There is no js error messages, leaflet just breaks.
This is my grunt file:
var $ = require('jquery');
window.jQuery = $;
//require boostrap.js for bootstrap components
var angular = require('angular');
require('ui.bootstrap');
require('showErrors');
require('leaflet');
require('leaflet-directive');
angular.module('common', [
require('angular-resource')
]);
var requires = [
'ngRoute',
'leaflet-directive',
'common',
'ui.bootstrap',
'ui.bootstrap.showErrors'
];
require('./common');
angular.module('app', requires).config(function($routeProvider) {
customRouteProvider.when('/common', {templateUrl: 'js/common/1.html'});
customRouteProvider.otherwise({redirectTo: '/'});
});
Html code:
<div ng-controller="mapController">
<div id="map" style="height: 440px; border: 1px solid #AAA;"></div>
</div>
mapController:
module.exports = function ($scope, leafletData) {
var map = L.map( 'map', {
center: [20.0, 5.0],
minZoom: 2,
zoom: 2
});
L.tileLayer( 'http://{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors | Tiles Courtesy of MapQuest <img src="http://developer.mapquest.com/content/osm/mq_logo.png" width="16" height="16">',
subdomains: ['otile1','otile2','otile3','otile4']
}).addTo( map );
}
But when I execute the code leaflet breaks and my map looks like:
I tried also with angular-leaflet-directive with standard and it still breaks. Did anyone face this issue before? Any suggestions?
in your file Html code
test with change style div: height: 80vh;
<div ng-controller="mapController">
<div id="map" style="height: 80vh; border: 1px solid #AAA;"></div>
</div>
And check the initialization the component life cycle:
Angular 6 is ngOnInit.
Ionic is ionViewDidEnter.
The idea is that booklet loading is done after initialization of the component.
This problem often occurs due to resizing of any parent container while the map is already initialized.
This my solution in Angular 12 link
If you are having this issue on Vue3 you need to import the CSS:
<script>
import "leaflet/dist/leaflet.css";

How to specify accessToken for Mapbox with Leaflet

From Mapbox site I tested this code and success:
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title></title>
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.cs
<style>
body { margin:0; padding:0; }
.map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id='map' class='map'> </div>
<script>
var map = new L.Map('map', {
center: new L.LatLng(51.505, -0.09),
zoom: 8,
layers: new L.TileLayer('https://a.tiles.mapbox.com/v3/mapbox.world-bright/{z}
});
</script>
</body>
</html>
How can I access my own map with markers and features? I suppose the "mapbox.world-bright" would be replaced by my own map.id, but how can I set the accessToken?
For some reasons I need to stick with Leaflet, and don't want to switch to mapbox.js.
It's just a matter of using the right url in L.TileLayer. You'll need to add your mapId and token and use the correct attribution. It's also much better if you load the tiles from multiple subdomains because your browser can handle up to four connection as once. Code example:
L.tileLayer('https://{s}.tiles.mapbox.com/v4/{mapId}/{z}/{x}/{y}.png?access_token={token}', {
attribution: '© Mapbox © OpenStreetMap',
subdomains: ['a','b','c','d'],
mapId: 'myMapId',
token: 'myUserToken'
});
To add the features of your map you'll need to query those in a separate request. Here's an example using jQuery. You'll need to swap the MAPID and TOKEN for your mapid and token ofcourse:
$.getJSON('http://a.tiles.mapbox.com/v4/MAPID/features.json?access_token=TOKEN', function (data) {
// Assuming the variable map contains your mapinstance
var geojson = L.geoJson(data).addTo(map);
map.fitBounds(geojson.getBounds());
});
Here's a working example on Plunker: http://plnkr.co/edit/h8F3kC?p=preview