Generating leaflet markers with forEach in Meteor.js - javascript

I am trying to generate a marker for every geotag in a database using Meteor and leaflet package which I've added through Meteorite.
I've been messing around with the following code and nothing seems to work:
Geoposts = new Meteor.Collection("geoposts");
Geoposts.insert(
{"location":
{"latitude": "40.4417",
"longitude": "-80.000"},
"message": "Hi, I am a message."}
);
if (Meteor.isClient) {
Template.sites.rendered = function() {
// create a map in the "map" div, set the view to a given place and zoom
var map = L.map('map').setView([40.4417, -80.0000], 13);
// add an OpenStreetMap tile layer
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
// add a marker in the given location, attach some popup content to it and open the popup
var myIcon = L.icon({
iconUrl: 'packages/leaflet/images/marker-icon.png',
shadowUrl: 'packages/leaflet/images/marker-shadow.png',
});
var coordForPin = Geoposts.find({location:{latitude:{}}, longitude:{}});
coordForPin.forEach(function(){
L.marker([coordForPin], {icon: myIcon}).addTo(map);
});
}};
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
})};
If anyone can help, it would be much appreciated! Thanks!!

The callback argument to cursor.forEach should take and use the document as an argument. Also, if your Geoposts collection is not static, consider observing your cursor to add/remove/change map markers reactively, rather than using forEach.

Related

Leaflet error when zooming after closing popup

I already saw the same question here: StackOverflow
But none of the answers helped or atleast I didn't understand it.
If I place a new marker on the map by clicking and then remove the marker by clicking again and then attempt to zoom, I get the error:
TypeError: Cannot read properties of null (reading '_latLngToNewLayerPoint')
at NewClass._animateZoom
A more simple example of this happening is when I click a marker to see the popup. After seeing the popup, I close the popup and then try to zoom and I get errors on every zoom.
When I first close the popup, I get a warning saying that listener not found which is odd, because I close the popup by simply clicking on the map and I DO have a listener for when I click on the map.
here is the code:
var mapLink = 'Esri';
var wholink = 'i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community';
var satelliteLayer = L.tileLayer(
'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
attribution: '© ' + mapLink + ', ' + wholink,
maxZoom: 18,
});
var osm = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap'
});
var mapboxUrl = 'https://api.mapbox.com/styles/v1/johnmichel/ciobach7h0084b3nf482gfvvr/tiles/{z}/{x}/{y}?access_token=pk.eyJ1Ijoiam9obm1pY2hlbCIsImEiOiJjaW9iOW1vbHUwMGEzdnJseWNranhiMHpxIn0.leVOjMBazNl6v4h9MT7Glw';
var mapboxAttribution = 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox'
var streets = L.tileLayer(mapboxUrl, { id: 'mapbox/streets-v11', tileSize: 512, zoomOffset: -1, attribution: mapboxAttribution });
var map = L.map("mapContainer", {
center: [lat, lng],
zoom: 10,
layers: [osm, satelliteLayer, streets],
maxZoom: 18,
minZoom: 10,
smoothWheelZoom: true, // enable smooth zoom
smoothSensitivity: 1, // zoom speed. default is 1
smoothZoom: true,
smoothZoomDelay: 1000 // Default to 1000
}).on('click', this.onMapClick);
map.on('moveend', this.onMapMoved)
var baseMaps = {
"OpenStreetMap": osm,
"Satellite": satelliteLayer,
"Mapbox Streets": streets
};
var kayakLaunchLayer = L.layerGroup([]);
var yourPin = L.layerGroup([]);
this.markerLayerGroup = L.layerGroup();
this.singleMarkerLayerGroup = L.layerGroup();
var layerControl = L.control.layers(baseMaps).addTo(map);
map.addLayer(kayakLaunchLayer);
map.addLayer(yourPin);
this.markerLayerGroup = kayakLaunchLayer;
this.singleMarkerLayerGroup = yourPin;
// layerControl.addOverlay(this.markerLayerGroup, "Kayak Launches");
// layerControl.addOverlay(this.singleMarkerLayerGroup, "Your Pin");
map.invalidateSize();
this.map = map;
this.map is a variable defined in data in my Vue component and so is this.singleMarkerLayerGroup and this.markerLayerGroup.
And this is the function where I actually add the markers to the this.markerLayerGroup so that I can see them as an overlay on the map:
var lat = launch.loc.coordinates[1];
var lng = launch.loc.coordinates[0];
var marker = L.marker([lat, lng]).addTo(this.markerLayerGroup).on('click', this.onMarkerClick);
var photoImgwithContent = `<h2>${launch.name}</h2><img src="${launch.images[0]}" height="150px" width="150px"/><h3></h3>${this.capitalizeFirstLetter(launch.waterType)}`;
marker.bindPopup(photoImgwithContent);
Now what is wrong with any of this? I have restructured the code to follow documentation as closely as possible and still stumped.
But strangely, if I turn off zoom animation by applying this map option: zoomAnimation:false, then the error is gone but the map look terrible without zoom animation.
This seems like a similar situation as in Uncaught TypeError: this._map is null (Vue.js 3, Leaflet), since you seem to use Vue.js 3, and the error occurs when zooming the map after some Layers/Popup are removed:
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
A solution consists in "unwrapping" / un-proxying the map and the Layer Groups (i.e. all Leaflet objects that you store in this Vue component data) whenever you use them, e.g. with Vue3's toRaw utility function:
var marker = L.marker([lat, lng])
.addTo(toRaw(this.markerLayerGroup));
See also the Vue 3 guide to Reduce Reactivity Overhead for Large Immutable Structures.

Two maps on the same page with Leaflet JS, second one not rendering properly

A project I'm working on requires 2 maps on the same page.
I've differeniatiated them using unique varibales and HTML id's, yet the second map never renders properly. It has grey tiles on it. However when I put the second map in the place where the first map is, it renders without any problems.
Map 1 JS
center: [ 0E-16 , 0E-16 ],
zoom: 1.75,
minZoom: 1.75,
}
let memory_map = new L.map('memory_map', memory_mapOptions);
let memory_cartodbAttribution = '© OpenStreetMap contributors, © CARTO';
let memory_layer = new L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {attribution: memory_cartodbAttribution}).addTo(memory_map)
memory_map.addLayer(memory_layer);
let memory_popup = new L.popup();
function memory_onMapClick(e) {
memory_popup
.setLatLng(e.latlng)
.setContent("You clicked the map at " + e.latlng.toString())
.openOn(memory_map);
}
memory_map.on('click', memory_onMapClick);
Map 2 JS
let future_mapOptions = {
center: [ 0E-16 , 0E-16 ],
zoom: 1.75,
minZoom: 1.75,
}
let future_map = new L.map('future_map', future_mapOptions);
let future_cartodbAttribution = '© OpenStreetMap contributors, © CARTO';
let future_layer = new L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {attribution: future_cartodbAttribution}).addTo(future_map)
future_map.addLayer(future_layer);
let future_popup = L.popup();
function future_onMapClick(f) {
future_popup
.setLatLng(f.latlng)
.setContent("You clicked the map at " + e.latlng.toString())
.openOn(future_map);
}
future_map.on('click', future_onMapClick);
Solutions I've Tried
I copied and pasted the code from the LeafletJS examples, but received the same issue of the map loading incorrectly. This example used a different map and attribution.
Moved the position of the JS code for LeafletJS to be directly above the map in HTML.
Double checked all the avriables are unique (They are).
Swapped the maps around to see if it was an issue with the Map 2 JS. It renderered OK when in Map 1's position on the page
Any help much appreciated!

MapBox pop-up descriptions on markers not showing when clicking

I've integrated a MapBox map with marker clustering. For some reason the descriptions/titles will not show when you click on the marker.
Any idea why this is happening or how to fix it?
The page: https://vpnarea.com/front/member/signuptest
My MapBox code:
<script>
L.mapbox.accessToken = 'pk.xxxxxxxxxxxxxxxxxxxxxxx';
var markers = L.markerClusterGroup();
$.getJSON("https://vpnarea.com/data2.geojson-copy", function(data) {
var geojson = L.geoJson(data, {
onEachFeature: function (feature, layer) {
layer.setIcon(L.mapbox.marker.icon({'marker-color': 'f5c200','marker-size': 'small'}));
}
});
markers.addLayer(geojson);
// CONSTRUCT THE MAP
var map = L.mapbox.map('map1', 'vpnarea.m9b2pf4n') .setView([60, -55], 3);
markers.addTo(map);
});
</script>
You'll need to bind popups in order for them to appear: Mapbox.js's L.mapbox.featureLayer does this by default, but you're using L.geoJson, which does not. So you'll need to check out the Leaflet documentation for .bindPopup and use it.

How can I style Mapbox markers being pulled in directly from Mapbox?

I am new to Mapbox, so please bear with me.
I have uploaded my geoJson to my Mapbox map and am now editing it via javascript, creating the map by calling the following function.
$scope.initMap = function() {
var map = L.mapbox.map('map', 'example.hk78fg64');
};
The map works fine, but I want to style the default markers. How can I style these markers being pulled in from Mapbox directly? All examples for styling them have the markers being created on the spot inside the geoJson function (view the expression below)
L.geoJson(geoJson, {
pointToLayer: L.mapbox.marker.style,
});
See the L.mapbox.map documentation:
$scope.initMap = function() {
var map = L.mapbox.map('map', 'example.hk78fg64', { featureLayer: {
pointToLayer: L.mapbox.marker.style }
});
};

How to change the map center in Leaflet.js

The following code initializes a leaflet map. The initialize function centers the map based on user location. How do I change the center of the map to a new position after calling the initialize function?
function initialize() {
map = L.map('map');
L.tileLayer('http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © CloudMade'
}).addTo(map);
map.locate({setView: true, maxZoom: 8});
}
For example:
map.panTo(new L.LatLng(40.737, -73.923));
You can also use:
map.setView(new L.LatLng(40.737, -73.923), 8);
It just depends on what behavior you want. map.panTo() will pan to the location with zoom/pan animation, while map.setView() immediately set the new view to the desired location/zoom level.
Use map.panTo(); does not do anything if the point is in the current view. Use map.setView() instead.
I had a polyline and I had to center map to a new point in polyline at every second. Check the code :
GOOD: https://jsfiddle.net/nstudor/xcmdwfjk/
mymap.setView(point, 11, { animation: true });
BAD: https://jsfiddle.net/nstudor/Lgahv905/
mymap.panTo(point);
mymap.setZoom(11);
You could also use:
var latLon = L.latLng(40.737, -73.923);
var bounds = latLon.toBounds(500); // 500 = metres
map.panTo(latLon).fitBounds(bounds);
This will set the view level to fit the bounds in the map leaflet.
I was looking for a way to change the bounds but without the animation. This worked for me:
var bounds = L.latLng(40.737, -73.923).toBounds();
map.fitBounds(bounds, {animation: false});
In the case of map-centering problem despite using panTo(),flyTo() or setView() try to adjust the map with map.invalidateSize():
setTimeout(function () {
map.invalidateSize(true);
}, 100);
jQuery sample:
$(document).ready(function () {
mymap.invalidateSize();
});

Categories