I'm using leaflet + leaflet-draw + #ngx-leaflet + #ngx-leaflet-draw in an Angular application.
I've tried everything, versions change, importing the modules .forRoot() and not, adding the js files in my angular.json file, remove node_modules, reinstall them, followed the guide on #ngx-leaflet-draw from scratch a hundred times.
No matter what I do, when I try to draw a rectangle it always throws this error:
Even though the handlers are present and ALL of them works perfectly except for the rectangle one (the only one I need)
I don't even know how to provide you with more specific informations if not for this:
leaflet: 1.5.1
leaflet-draw: 1.0.4
#asymmetrik/ngx-leaflet: 6.0.1
#asymmetrik/ngx-leaflet-draw: 5.0.1
I'm stuck on this stupid error and I don't know how to get over it. Please help!
here's a repo for demo: https://github.com/caiusCitiriga/leaflet-rect-drawer
There are a couple of issues:
The draw options aren't quite right. This isn't actually causing the error, though.
There's a bug leaflet-draw that causes the exception you're seeing.
Leaflet Draw Options
square is not a draw option. The correct option is rectangle. Additionally, all of the handlers are enabled by default. So, you only need to turn off the ones you don't want.
So, I think what you want is in your app.component.ts file:
public drawOptions = {
position: 'topright',
draw: {
marker: {
icon: L.icon({
iconSize: [25, 41],
iconAnchor: [13, 41],
iconUrl: 'assets/marker-icon.png',
shadowUrl: 'assets/marker-shadow.png'
})
},
polygon: false,
circlemarker: false
}
};
The above will make sure that marker, circle, rectangle, and polyline are enabled and the others are disabled. You want to make sure to add the leaflet assets png files to the list of assets being exported by Angular CLI in your angular.json file.
Identifying and Fixing The Error
There's something weird about leaflet-draw's build that's causing the source maps to not work. To get them working, I had to directly import the leaflet.draw-src.js file.
At the top of app.component.ts, I added:
import * as L from 'leaflet';
import '../../node_modules/leaflet-draw/dist/leaflet.draw-src.js'; // add this
That allows you to put a breakpoint in the leaflet-draw code to figure out what's going on. Upon doing that, it looks like there's a variable called type that isn't declared before it's assigned to. The code is being run in strict mode, so this will throw an exception. This looks to be a bug in leaflet-draw.
Solution 1: Disable ShowArea
First, you can disable showArea, which will prevent the problem code from running. To do this, modify the drawOptions:
public drawOptions = {
position: 'topright',
draw: {
marker: {
icon: L.icon({
iconSize: [25, 41],
iconAnchor: [13, 41],
iconUrl: 'assets/marker-icon.png',
shadowUrl: 'assets/marker-shadow.png'
})
},
rectangle: { showArea: false }, // disable showArea
polyline: true,
polygon: false,
circlemarker: false
}
};
This isn't a great solution, cause you lose the showArea functionality.
Solution 2: Disable Strict Mode
The other solution is to disable strict mode for the Typescript compiler.
To do this, edit your tsconfig.json and tsconfig.app.json files, adding "noImplicitUseStrict": true under the compilerOptions property.
This solves the problem, but now you're not running your code in strict mode, which can lead to other issues.
there is a typing probleme inside leaflet draw file
Unfortunatly, there is no more support on this project
You can update node-package module and fix the problem, here is my solution :
install last leaflet and leaflet-draw version
for me :
"leaflet": "^1.7.1",
"leaflet-draw": "^1.0.4",
And install patch-package : https://www.npmjs.com/package/patch-package
go to node-module/leaflet-draw/dist/leaflet.draw.js
update the package
replace this part of code : (I can't give you the line cause it's a minified file, so you have to ctrl+f to find the location.)
{var a,n,o=L.Util.extend({},t,o)
by this :
{var type;var a,n,o=L.Util.extend({},t,o)
After node module package updated, you have to create a node module patch
to do this, use patch-package command :
npx patch-package leaflet-draw
Last things is to tell angular to replace the correct leaflet-draw file
To do this, you have to go inside your angular package.json
and add this line :
"postinstall": "patch-package"
like this:
"scripts": {
"postinstall": "patch-package",
"build": "ng build",
"lint": "ng lint",
"ng": "ng",
},
Remove your node-module package
Make new install (npm install)
Now you can use the rectangle draw fnunctionnality
if you just need in local, you just need to update the leaflet-draw.js file.
I 'fixed' it with
rectangle: <any>{ showArea: false },
Related
The problem is that the leaflet map inside the vue3 App loads perfectly and looks great. Also, when you click on a location with two icons in the same position, they open perfectly, but when you click on the same place again, the icons disappear and the "spider" remains visible (see picture).
spider remains
The methods in the Vue3 App are:
methods:{
setupMarkers(){
this.markers.clearLayers();
this.cursesData.forEach(cursa =>this.ficaMarkers(cursa));
this.map.addLayer(this.markers);
},
setupLeafletMap(){
this.map=L.map("mapContainer").setView(this.center,6);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",{
attribution:'OpenStreetMap',
}).addTo(this.map);
this.markers= L.markerClusterGroup({
//spiderfyOnMaxZoom: true,
});
},
ficaMarkers(cursa){
this.markers.addLayer(L.marker([cursa.coordenades[0],cursa.coordenades[1]],{title:cursa.nom})
.bindPopup(cursa.distancies)
)
},
},
If someone could help me, I would be very grateful.
Thanks.
It is a similar issue as in Uncaught TypeError: this._map is null (Vue.js 3, Leaflet) :
What seems to be the culprit is the proxying of this.map by Vue, which seems to interfere with Leaflet events (un)binding. It looks like Vue 3 now automatically performs deep proxying, whereas Vue 2 was shallow.
In your case, the same thing happens for this.markers (which is the Leaflet MarkerClusterGroup).
A solution consists in "unwrapping" / un-proxying the map and the mcg whenever you use them, e.g. with Vue3's toRaw:
toRaw(this.map).addLayer(toRaw(this.markers));
Then we retrieve the normal MCG behaviour, i.e. if you click on the cluster while it is already spiderfied, nothing happens (whereas initially the Markers were collapsing, but the spider legs were remaining indefinitely)
Fixed CodeSandbox: https://codesandbox.io/s/markers-hide-spiders-stay-forked-l2ruqh?file=/src/App.vue
I started using react-native-animatable. It is similar to Animate.css with many pre-defined animations for React Native. Remembering all the different animation names is tricky, how do I set auto-complete in VSCode for the different animation names:
The project has a definition file. I am not working with Typescript but I guess auto-completion wouldn't mind, right? How do I set it up?
What I've tried so far:
I've added a file named tsconfig.json in the root:
{
"allowJs": true,
"compilerOptions": {
"noUnusedLocals": true,
"module": "commonjs",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true
},
"files": ["typings/react-native-animatable.d"]
}
I have copied the 3rd party's definition to a directory named "typings".
Still no luck.
I'm pretty sure typings definition files end in .d.ts While I'm not sure what the exact problem or solution is this page - under the 'quick fix' heading may point you in the right direction.
I faced this issue in 16.11 react but by pasting three files in react folder in node_modules: which are index.d.ts and experimental.d.ts and global.d.ts. I got these from my old project which is 16.9 react.
I'm trying to display a clustered map with Mapbox GL JS.
Using this example from the documentation: https://www.mapbox.com/mapbox-gl-js/example/cluster/, I'd like to show a marker icon instead of a circle for unclustered points.
I modified the last addLayer call like this :
map.addLayer({
id: "unclustered-point",
type: "symbol",
source: "companies",
filter: ["!has", "point_count"],
layout: {
"icon-image": "marker-15", // THIS SHOULD BE A MARKER
"icon-size": 5 // ZOOMED FOR DEMO
},
});
Here is the result I got :
Why can't I get access to Maki Icons like it is suggested here : Mapbox GL js available icons
Without a link to your (non) working example, it's hard to diagnose fully, but one possibility is that that icon is not included in your style.
You could try starting from a style that definitely includes them, like these: https://github.com/mapbox/mapbox-gl-styles
So I am writing an app which allows an admin user to create a journey around a specific location with different stopping points.
For displaying a map, adding markers, flyTo location and etc I am using Mapbox GL.
I was using cURL implementation of Mapbox API to get driving directions and then draw a line on a map
So as an example of a cURL call I recieve a list of coordinates which represent my directions.
The Problem comes when I try to connect these points on a map.
As an example of HTML with some JS
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title></title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.18.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.18.0/mapbox-gl.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id='map'></div>
<script>
mapboxgl.accessToken = '<ACCESS TOKEN>';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v8',
center: [-122.486052, 37.830348],
zoom: 15
});
map.on('load', function () {
map.addSource("route", {
"type": "geojson",
"data": {
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
[-155.088899,19.722942],[-155.08565,19.72472],[-155.084661,19.723701],[-155.083569,19.723139],[-155.079557,19.722262],[-155.074227,19.721938],[-155.069939,19.722545],[-155.070061,19.721225],[-155.07007,19.711726]
]
}
}
});
map.addLayer({
"id": "route",
"type": "line",
"source": "route",
"layout": {
"line-join": "round",
"line-cap": "round"
},
"paint": {
"line-color": "#888",
"line-width": 8
}
});
});
</script>
</body>
</html>
You can see a set of coordinates that will be connected to draw a line. I was wondering if there is a way to connect these points so that the line will follow only the road (for driving)?
To explain it better, this is a close zoom of the output
I know it's quite generic explanation of my problem, but I hope it's understandable.
I have been trying to do some magic with Mapbox Gl Directions API but no luck, as I have to add a contoller which I dont want to. I only need to draw a route and not allow a public user to be able to modify it.
Any advices?
Not sure if I understood correctly, but when you send you request to get directions include in the url 'overview=full'. This will return a more detailed path, so you have no need to use Matching API after.
Example:
`https://api.mapbox.com/directions/v5/mapbox/driving/-74.50,40;-80,50?overview=full&geometries=geojson&access_token=
I've been trying to do this today and succeded to get directions into a map and remove the start and end control by pulling down the mapbox-gl-directions project from git hub and making a minor mod to src/directions.js
I commented out lines 48 to 52
// Add controllers to the page
//new Inputs(inputEl, store, this.actions, this.map);
//new Instructions(directionsEl, store, {
// hoverMarker: this.actions.hoverMarker,
// setRouteIndex: this.actions.setRouteIndex
//}, this.map);
This was relatively easy to test with the setup in npm and my own test files by running the npm setup as per https://github.com/mapbox/mapbox-gl-directions/blob/master/CONTRIBUTING.md
npm install & npm start & open http://localhost:9966/example/
I also added the line:
localStorage.setItem('MapboxAccessToken', '<TOKEN HERE>');
below the require('../); in example/index.js. While you have the example running in npm you can access a new bundled version of the plugin from http://localhost:9966/example/bundle.js
I was then able to change the line
<script src='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-directions/v2.0.0/mapbox-gl-directions.js'></script>
to
<script src='http://localhost:9966/example/bundle.js'></script>
There's a whole bunch of magic going in on in the example runner in npm which I don't know anything about but it all just worked on my machine. Hope this helps. The directions line works with animations and pitch, zoom and bearing animations. See a screen grab below:
UPDATE: Adding reply to here so I can show a screen grab. #Andrejus, as this hack relies on the mapbox gl directions plugin behaviour rather than drawing the paths from scratch you get road following built in and you have access to the directions API to add waypoints to do your A->B->C->D as so:
map.on('load', function() {
directions.setOrigin(start);
directions.addWaypoint(0, [-0.07571203, 51.51424049]);
directions.addWaypoint(1, [-0.12416858, 51.50779757]);
directions.setDestination(end);
});
The documentation says you can have up to 25 way points.
The mapbox-gl-directions plugin doesn't have an option to turn off the on-screen controls, they are added in the onAdd(map) method of the Directions class which is called when the directions are added to the map. I wanted to see if I could remove them earlier and was experimenting, thus the hack. To make a flexible solution, it might be possible to add an option passed in to the constructor of the Directions class. There are other options passed in there although these seem to be bound to parameters for the call to the Directions API:
var directions = new mapboxgl.Directions({
unit: 'metric',
profile: 'cycling'
});
So there might be a better solution than that. I've been using Mapbox for <1 day and don't know much about how its written or structured.
Note also that the code alterations are in a plugin, not the core of mapbox gl, so relatively isolated. BTW this plugin is a wrapper for the cURL API you were calling which returned the array of points. Presumably the source on GitHub will include code which does the road following where it renders the line, if that's definitely what you want to do.
Actually it was easier that I thought, All I had to do is to get a response from directions API, and pass a returned array to Mapbox Map Matching, that way it returns a perfect route. All documented in Mapbox API
We use leafletJS to show maps with round about 100 markers. Some of these markers are located on exact the same position. Marker2 is above Marker1 so Marker1 isn't visible. Is there a way to rotate Markers in a way that you can see there are more then one marker?
may be you should look at https://github.com/Leaflet/Leaflet.markercluster plugin
here demo - http://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-realworld.388.html
The drawback with walla's answer is that Leaflet.markercluster requires clustering, which may not be an option depending on your requirements i.e. you need to always display individual markers.
OverlappingMarkerSpiderfier-Leaflet (a bit of a mouthful) works well in this case and it's fairly well documented. It displays a 'spider' of markers on click only if they overlap i.e. if the zoom level increases so markers don't overlap, then it won't 'spider' on click, which is quite nice. Demo.
It's available as a NPM package but it isn't a proper ES module, so usage is a bit trickier than usual if you're expecting an ES module:
// Need to specifically import the distributed JS file
import 'overlapping-marker-spiderfier-leaflet/dist/oms';
// Note access to constructor via window object
// map refers to your leaflet map object
const oms = new window.OverlappingMarkerSpiderfier(map);
oms.addListener('click', (marker) => {
// Your callback when marker is clicked
});
// Markers need to be added to OMS to spider overlapping markers
markers.forEach((marker) => {
oms.addMarker(marker);
});
// Conversely use oms.removeMarker(marker) if a marker is removed
Alternatively there is a forked version (confusingly) called OverlappingMarkerSpiderfier that is a proper ES module so you can do:
import OverlappingMarkerSpiderfier from 'overlapping-marker-spiderfier'
const oms = new OverlappingMarkerSpiderfier(map);
However as of 24 Jan 2020 there's a fair bit of divergence based on commits between the two so YMMV.
FWIW I'm using the original.
If anyone is looking working sample for Angular below are the steps,
Install it via npm: npm i --save overlapping-marker-spiderfier-leaflet
Then import it into the component where you need it: import 'overlapping-marker-spiderfier-leaflet/dist/oms';
Add this line on top of the file where you import it: const OverlappingMarkerSpiderfier = (<any>window).OverlappingMarkerSpiderfier;
Add the oms markup like that: this.oms = new OverlappingMarkerSpiderfier(this.map, { nearbyDistance: 20, keepSpiderfied: true });
Add the markers to oms at the same place where you add your markers to the map so oms can track them properly this.oms.addMarker(marker);
xlm is already gave a complete answer. Thanks to him for that answer. But this is a slightly changed answer that worked for me in angular.
we had the same problem, follows the jsFiddle with the solution we found http://jsfiddle.net/atma_tecnologia/mgkuq0gf/2/
var marker1 = new google.maps.Marker({
position: myLatLng,
map: map,
icon: {
url: image,
size: new google.maps.Size(134,130), //different sizes
},
zIndex: 2, //different overlays
title: '1ยบ marker',
});