Leaflet breaks on load - leaflet

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";

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

Layer control using leaftejs and vuejs

Everyone I am a junior developer at NESAC(ISRO).
I am working on a project with vue JS and leaflet JS. So my task is:-
Using Leaflet JS, I have to render a map on the screen.
Set markers at "n" specific locations on the renderd map.
Create a sidebar with a checkbox of various entities such as cities, restaurants, parks etc.
Develop a Vue app such that, I create my different components on the components folder, so that all my components go through App.vue file and gets renderd at the index.html, i.e. my browser.
And, now I have to make a Layer control function such that each of my entities gets different reactions. Eg. If I click the restaurant checkbox at the sidebar, then all my restaurant leaflet markers should be shown on the screen, but each entity should have different reactivity.
Github Link.
You can use npm package for that - Vue2Leaflet
Here is docu: https://vue2-leaflet.netlify.app
And simple Map with Vue.js and leaflet:
<template>
<div style="height: 350px;">
<div class="info" style="height: 15%">
<span>Center: {{ center }}</span>
<span>Zoom: {{ zoom }}</span>
<span>Bounds: {{ bounds }}</span>
</div>
<l-map
style="height: 80%; width: 100%"
:zoom="zoom"
:center="center"
#update:zoom="zoomUpdated"
#update:center="centerUpdated"
#update:bounds="boundsUpdated"
>
<l-tile-layer :url="url"></l-tile-layer>
</l-map>
</div>
</template>
<script>
import {LMap, LTileLayer} from 'vue2-leaflet';
export default {
components: {
LMap,
LTileLayer,
},
data () {
return {
url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
zoom: 3,
center: [47.413220, -1.219482],
bounds: null
};
},
methods: {
zoomUpdated (zoom) {
this.zoom = zoom;
},
centerUpdated (center) {
this.center = center;
},
boundsUpdated (bounds) {
this.bounds = bounds;
}
}
}
</script>
It's just a wrapper for a leaflet and you have complete access to all the leaflet functions through:
mounted() {
this.$nextTick(() => {
this.map = this.$refs.map.mapObject;
});
}
I think that can be a good start for you.

Using Leaflet.AwesomeMarkers plugin with Font Awesome 5?

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
})

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>

Markers not appearing using the Mapbox GL JS API

I'm following these docs, but the code below does not render a marker. Any ideas why?
mapboxgl.accessToken = "pk.eyJ1IjoiZGlsbHBpeGVsIiwiYSI6ImNqM3A1YWV4czAwa3cyd3BmeWR4OTJ4NGEifQ.atNs-3fdoNghDcrdKwtIkA";
var map = new mapboxgl.Map({
container: "map",
center: [-74.50, 40],
zoom: 6,
scrollZoom: false,
style: "mapbox://styles/mapbox/light-v9",
});
map.addControl(new mapboxgl.NavigationControl(), "top-left");
var marker = new mapboxgl.Marker().setLngLat([-74.50, 40]).addTo(map);
#map {
height: 320px;
}
<link href="//api.mapbox.com/mapbox-gl-js/v0.36.0/mapbox-gl.css" rel="stylesheet"/>
<script src="//api.mapbox.com/mapbox-gl-js/v0.36.0/mapbox-gl.js"></script>
<div id="map"></div>
Nevermind. Just found the answer: https://github.com/mapbox/mapbox-gl-js/issues/4384
Also answered here: Mapbox GL - my basic, default marker won´t show up on the map