I have a map in Javascript on my landing page.
I set several markers and have them info Windows to show when clicked.
When you click a marker it shows the info window. The trouble is there is no way to close the others.
I could closehere used to be a .markers property to get all markers so i could close each in a for loop.
This no longer exists.
I've tried using a shared info window. It doesn't work since there's no way to set the content in the click event of the marker.
This seems like something that should be simple.
Any ideas?
Code for reference:
function addMarker({maps,map,position,html,image,center,allowClick,location}){
// Create InfoWindow
if (infowindow) {
infowindow.close();
}
const newHtml=` <div
style={{backgroundColor:"white",width:"300px",height:"250px",borderRadius:"8px",boxShadow:"0 2px 7px 1px rgb(0 0 0 / 30%",boxSizing: "border-box",
overflow: "hidden",padding:"12px"}}
>
${location.name}
${location.phone}
${location.address}
</div>`
infowindow = new maps.InfoWindow({
content: newHtml,
zIndex: 2,
maxWidth: 500,
});
// Add Marker with infowindow
const marker = new maps.Marker({
map,
position,
icon: image,
infowindow,
});
if(allowClick){
// Add Click Event to Marker
maps.event.addListener(marker, "click", function(arg) {
//NEED TO CLOSE OTHERS HERE!!!
// Open Info Window
infowindow.open(map, marker);
// Center Map on Marker
if(center){
map.setCenter(marker.getPosition());
}
});
}
return marker;
}
Keep the infowindow in a variable. Whenever you open another marker, it would close the previous one.
const myLatLng = new google.maps.LatLng(10.795871902729937, 106.64540961817315),
myOptions = {
zoom: 11,
center: myLatLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
},
map = new google.maps.Map(document.getElementById('map-canvas'), myOptions)
let infowindow
const positions = [
{lat: 10.876800062989094, lng: 106.73742011622002},
{lat: 10.781684787932484, lng: 106.62806039709115},
{ lat: 10.825433659372413,lng: 106.5160903436142 }
]
const markers = positions.map(position => {
const marker = new google.maps.Marker({
position,
map,
});
marker.setMap(map)
return marker
})
// Add click event for every marker to open new infowindow
markers.forEach((marker, index) => {
marker.addListener("click", () => {
if(infowindow) infowindow.close() // close previous infowindow
let content = `Marker ${index}`
infowindow = new google.maps.InfoWindow({
content,
})
infowindow.open(map, marker)
})
})
Code example
Related
I have added MapboxDirections control to by map using the normal method, which is working.
map.current = new mapboxgl.Map({
container: mapContainer.current,
style: 'mapbox://styles/mapbox/outdoors-v11',
center: [lng, lat],
zoom: zoom
});
directions.current = new MapboxDirections({
accessToken: mapboxgl.accessToken,
unit: 'metric',
profile: 'mapbox/cycling'
});
map.current.addControl(directions.current, 'top-left');
I want to add a SAVE button allowing me to get all the waypoints/coordinates of the route (that I can see on the map) but I cannot find a way to extract the coordinates out of the mapboxgl.Map or MapboxDirections object. I want to be able to save/download the results to a file.
Any ideas?
I'm writing my first larger project in react and I need to set up markers in my map component. I've set everythin up as it is shown in the tutorial however it is not working correctly with my code and the markers are not shown on map.
const dummyGeoJson = {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: {},
geometry: {
type: "Point",
coordinates: [16.959285736083984, 52.40472293138462]
}
}
]
};
class EventMap extends React.Component {
componentDidMount() {
this.map = L.map("map", {
center: [51.9194, 19.1451],
zoom: 6
});
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
maxZoom: 20
}).addTo(this.map);
var geoJsonLayer = L.geoJSON().addTo(this.map);
geoJsonLayer.addData(dummyGeoJson);
}
render() {
return <Wrapper width="100%" height="800px" id="map" />;
}
}
From what i've read in official leaflet tutorial this code should create a new geojson layer and create a marker in a position referenced in geojson but actually the only thing that is shown is my tile layer.
You need to use a pointToLayer function in a GeoJSON options object when creating the GeoJSON layer like this:
componentDidMount() {
const map = L.map("map", {
center: [51.9194, 19.1451],
zoom: 6
});
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
maxZoom: 20
}).addTo(map);
L.geoJSON(dummyGeoJson, {
pointToLayer: (feature, latlng) => {
return L.marker(latlng, { icon: customMarker });
}
}).addTo(map);
}
You can then pass a customMarker variable to define some options in order to make your marker be displayed on the UI
Demo
Welcome to SO!
The most probable reason is that you bundle your app (typically with webpack), but the build misses Leaflet default icon images.
So your Marker is there, but you cannot see it because its icon image is missing.
An easy way to debug it is to use another icon instead, as suggested in kboul's answer, or even more simply by using a CircleMarker.
Then to solve the issue of the build engine missing to process the default icon images, see Leaflet #4968:
explicitly import / require the Leaflet default icon images and modify the L.Icon.Default options to use the new imported paths
or use the leaflet-defaulticon-compatibility plugin (I am the author).
I am trying to load a simple leaflet map in my Ionic 2 app. Unfortunately not all tiles are loaded currectly until a moving the map.
this.map = new L.Map('mainmap', {
zoomControl: false,
center: new L.LatLng(40.731253, -73.996139),
zoom: 12,
minZoom: 4,
maxZoom: 19,
layers: [this.mapService.baseMaps.OpenStreetMap],
attributionControl: false
});
There are a couple of solutions for this problem:
1- Add "./node_modules/leaflet/dist/leaflet.css" in the styles array in `angular.json'.
2- Invalidate size when a map is ready:
onMapReady(map: L.Map) {
setTimeout(() => {
map.invalidateSize();
}, 0);
}
Add this to your template:
<div style="height: 300px;"
leaflet
(leafletMapReady)="onMapReady($event)">
</div>
And this will bind onMapReady method which you have in your component.
3- Install Leaflet typings for Typescript:
npm install --save-dev #types/leaflet
Vanilla JavaScript:
1- Validate the size of map:
onMapReady(map: L.Map) {
setTimeout(() => {
map.invalidateSize();
}, 0);
}
2- Add leaflet stylesheet leaflet/dist/leaflet.css in the <head> of your document.
this work for me fine :
this.map = L.map('map');
const self = this;
this.map.on("load",function() { setTimeout(() => {
self.map.invalidateSize();
}, 1); });
this.map.setView([36.3573539, 59.487427], 13);
Just put the creation of the map into the Ionic ionViewDidEnter lifecycle method. Much cleaner than any setTimeout hack ;)
import { Map, tileLayer } from 'leaflet';
...
ionViewDidEnter(): void {
this.map = new Map('map', {
center: [48.1351, 11.5819],
zoom: 3
});
const tiles = tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
minZoom: 3,
attribution: '© OSM'
});
tiles.addTo(this.map);
}
i´m using the openlayers drawing example inside my mobile JS (qooxdoo) app and all works fine except that the drawing cursor is above the viewport
so I can draw but I don´t see the cursor and I can only see the drawing after I scroll down.
I have used this qooxdoo example as a base. I have also added all the css rules from the openlayers example to my qooxdoo styles.
Seems like a css position issue, but I can´t seem to find it.
Any help would be appreciated.
/**
* Loads JavaScript library which is needed for the map.
*/
_loadMapLibrary: function() {
var self = this;
var req = new qx.bom.request.Script();
var options = {
singleTile: true,
ratio: 1,
isBaseLayer: true,
wrapDateLine: true,
getURL: function() {
var center = self._map.getCenter().transform("EPSG:3857", "EPSG:4326"),
size = self._map.getSize();
return [
this.url, "¢er=", center.lat, ",", center.lon, "&zoom=", self._map.getZoom(), "&size=", size.w, "x", size.h].join("");
}
};
req.onload = function() {
var vector = new OpenLayers.Layer.Vector('Vector Layer', {
styleMap: new OpenLayers.StyleMap({
temporary: OpenLayers.Util.applyDefaults({
pointRadius: 16
}, OpenLayers.Feature.Vector.style.temporary)
})
});
// OpenLayers' EditingToolbar internally creates a Navigation control, we
// want a TouchNavigation control here so we create our own editing toolbar
var toolbar = new OpenLayers.Control.Panel({
displayClass: 'olControlEditingToolbar'
});
toolbar.addControls([
// this control is just there to be able to deactivate the drawing
// tools
new OpenLayers.Control({
displayClass: 'olControlNavigation'
}), new OpenLayers.Control.ModifyFeature(vector, {
vertexRenderIntent: 'temporary',
displayClass: 'olControlModifyFeature'
}), new OpenLayers.Control.DrawFeature(vector, OpenLayers.Handler.Point, {
displayClass: 'olControlDrawFeaturePoint'
}), new OpenLayers.Control.DrawFeature(vector, OpenLayers.Handler.Path, {
displayClass: 'olControlDrawFeaturePath'
}), new OpenLayers.Control.DrawFeature(vector, OpenLayers.Handler.Polygon, {
displayClass: 'olControlDrawFeaturePolygon'
})]);
var osm = new OpenLayers.Layer.OSM();
osm.wrapDateLine = false;
map = new OpenLayers.Map({
div: 'googleMap',
projection: 'EPSG:900913',
numZoomLevels: 18,
controls: [
new OpenLayers.Control.TouchNavigation({
dragPanOptions: {
enableKinetic: true
}
}), new OpenLayers.Control.Zoom(), toolbar],
layers: [osm, vector],
center: new OpenLayers.LonLat(0, 0),
zoom: 1,
theme: null
});
// activate the first control to render the "navigation icon"
// as active
toolbar.controls[0].activate();
}
req.open("GET", this._mapUri);
req.send();
},
Please check the z-Index of the cursor's class. The best way is to modify the z-Index through Chrome's debugger console or Firebug.
Is there any live example of your application available?
According to the documention a marker is optional with an infoWindow, so how is this achieved please? I have tried infowindow.open(map) and infowindow.open(map,null) but both produce nothing.
If the position is set, there is no problem showing the info window
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 6,
center: {lat: 55.6761, lng: 12.5683},
mapTypeId: google.maps.MapTypeId.TERRAIN
});
var infowindow = new google.maps.InfoWindow({
content: "Copenhagen"
});
infowindow.setPosition({lat: 55.6761, lng: 12.5683});
infowindow.open(map);
}
infowindow.open(map) makes no sense since you need to specify the position where the infowindow should open, also it has a tapered stem which specifies the location where it should point.
According to the documentation of Infowindows- InfoWindows may be attached to either Marker objects (in which case their position is based on the marker's location) or on the map itself at a specified LatLng.
So if you donot want the marker to open the infowindow, use the map click event-
var iwindow= new google.maps.InfoWindow;
google.maps.event.addListener(map,'click',function(event)
{
iwindow.setContent(event.latLng.lat()+","+event.latLng.lng());
iwindow.open(map,this);
iwindow.open(map,this);
});
And to close a InfowWindow- infowindow.setMap(null);
Hope that cleared your doubts.
Since the api has changed, it is not possible to set position on info window any more. the solution i found is to add a marker to the map with visibility false:
this.map.addMarker({
position: {
'lat': sites[0].latitude,
'lng': sites[0].longitude
},
// setting visible false since the icon will be the poi icon
visible: false
}).then((marker: Marker) => {
this.htmInfoWindow.open(marker);
});