With help of the StackOverflow community I built a leaflet map with markers for blogdata and articledata. The blogdata represents the IDs and geoloations of newsrooms and the articledata are the locations from articles the newsrooms wrote. So there are several articles per newsroom and I connected those with polylines (see picture below).
What I'd like now to do is make that leaflet map searchable, not for cities or countries but for the newsrooms ID. And I'd like to manage blurring all the other markers and lines out and zooming to the searched blog and it's connected articles.
This is what I got so far:
function myFunction() {
var map = L.map('map').setView([51.101516, 10.313446], 6);
// improve experience on mobile
if (map.tap) map.tap.disable();
L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}', {
attribution: 'Tiles © Esri — Esri, DeLorme, NAVTEQ',
maxZoom: 16
}).addTo(map);
map._layersMinZoom=5;
var newsroomsById = {};
for(i=0; i<newsrooms.length; i++) {
newsroomsById[newsrooms[i].ID] = newsrooms[i];
}
for(i=0; i<articles.length; i++) {
// retrieve newsroom
var newsroom = newsroomsById[articles[i].ID];
// draw your polyline
var latlngs = [
[articles[i].lat, articles[i].long],
[newsroom.lat, newsroom.long]
];
var polyline = L.polyline(latlngs, {
color: 'grey',
weight: 2,
opacity: 0.5,
smoothFactor: 1,
}).addTo(map);
var room_marker = L.circleMarker([newsroom.lat, newsroom.long], {
radius: 3,
color: '#29D3A0',
fillColor: '#29D3A0',
fillOpacity: 1,
}).addTo(map);
room_marker.bindPopup("<strong style='color: #84b819'>Newsroom </strong>" + newsroom.ID + "<br>").openPopup();
var popup = L.popup();
var art_marker = L.circleMarker([articles[i].lat, articles[i].long], {
radius: 2,
color: '#000',
fillColor: '#000',
fillOpacity: 1,
}).addTo(map);
}
}
And this is how the map looks like (black is article, green is newsroom/blog)
EDIT:
To make the map searchable use the Leaflet plugin L.Search.Control
It's difficult to answer the search part of the question. I think you'll have to describe a use case for that.
However, once you have the ID of the newsroom you want to highlight, you can change the opacity of your polylines and circleMarkers using setOption
However, your code needs some adjustments: you need to keep an array of your markers and keep the ID of the newsrooms in the markers.
Another thing: you should not create newsroom markers in the article loop; it creates as many newsroom markers as your number of articles.
Here is a proposition (selection is made by clicking on the newsroom marker):
var selectedNewsroom = 0;
var newsroomsById = {};
// create newsroom markers
var newsroomMarkers = [];
for(i=0; i<newsrooms.length; i++) {
newsroomsById[newsrooms[i].ID] = newsrooms[i];
var room_marker = L.circleMarker([newsrooms[i].lat, newsrooms[i].long], {
radius: 20,
color: '#000',
opacity: .4,
fillOpacity: .4,
}).addTo(map);
//room_marker.bindPopup("<strong style='color: #84b819'>Newsroom </strong>" + newsrooms[i].ID + "<br>");
room_marker.ID = newsrooms[i].ID; // associate marker with newsroom
room_marker.on('click', function(e) {
console.log('clicked on ' + e.target.ID);
changeSelection(e.target.ID);
});
newsroomMarkers.push(room_marker); // keep marker reference for later
}
// create article markers and connections to newsrooms
var articleMarkers = [];
for(i=0; i<articles.length; i++) {
// retrieve newsroom
var newsroom = newsroomsById[articles[i].ID];
// draw your polyline
var latlngs = [
[articles[i].lat, articles[i].long],
[newsroom.lat, newsroom.long]
];
var polyline = L.polyline(latlngs, {
color: '#000',
weight: 1,
opacity: .4,
smoothFactor: 1,
}).addTo(map);
var art_marker = L.circleMarker([articles[i].lat, articles[i].long], {
radius: 2,
color: '#000',
fillColor: '#000',
opacity: .4,
fillOpacity: .4,
}).addTo(map);
art_marker.connection = polyline; // associate polyline with marker
art_marker.newsroomID = newsroom.ID;
articleMarkers.push(art_marker); // keep marker reference for later
}
// highlight or blur newsrooms base on which is selected
function changeSelection(newsroomID) {
// deselect everything
for(i=0; i<articleMarkers.length; i++) {
articleMarkers[i].setStyle({ opacity: .4, fillOpacity: .4 });
articleMarkers[i].connection.setStyle({ opacity: .4 });
}
for(i=0; i<newsroomMarkers.length; i++) {
newsroomMarkers[i].setStyle({ opacity: .4, fillOpacity: .4 });
}
if(selectedNewsroom == 0 || selectedNewsroom != newsroomID) {
selectedNewsroom = newsroomID;
for(i=0; i<articleMarkers.length; i++) {
if(articleMarkers[i].newsroomID == newsroomID) {
articleMarkers[i].setStyle({ opacity: 1, fillOpacity: 1 });
articleMarkers[i].connection.setStyle({ opacity: 1 });
}
}
for(i=0; i<newsroomMarkers.length; i++) {
if(newsroomMarkers[i].ID == newsroomID) {
newsroomMarkers[i].setStyle({ opacity: 1, fillOpacity: 1 });
}
}
}
else {
selectedNewsroom = 0;
}
}
And a working example.
Related
I have a leaflet map with polyline data in. The polyline is styled how I want but what I would like is to have a marker at the centre of each line. Is this possible and if so what changes to the below do I need to make?
var pathstyling = {
stroke: true,
fillColor: "#b5b5b5",
color: "#b5b5b5",
weight: 5,
opacity: 1,
fillOpacity: 0.6,
dashArray: 10,
};
const path = L.geoJSON(path_line, {
style: pathstyling,
})
.bindPopup(function (layer) {
let cap_name = layer.feature.properties.name.replace(
/(^\w{1})|(\s+\w{1})/g,
(letter) => letter.toUpperCase()
);
return `<p>${cap_name}</p><a href="https://${layer.feature.properties.link}" target="_blank">View<a>`;
/******/
})
.addTo(map);
You can simply do this with leaflet core:
function calcMiddleLatLng(map, latlng1, latlng2) {
// calculate the middle coordinates between two markers
const p1 = map.project(latlng1);
const p2 = map.project(latlng2);
return map.unproject(p1._add(p2)._divideBy(2));
}
function createMiddleMarkers(line){
var latlngs = line.getLatLngs();
for(var i = 1; i < latlngs.length; i++){
var left = latlngs[i-1];
var right = latlngs[i];
var newLatLng = calcMiddleLatLng(map,left,right);
L.marker(newLatLng).addTo(map);
}
}
createMiddleMarkers(layer);
https://jsfiddle.net/falkedesign/g7e8w9tz/
I am trying to fix a bug in existing code.
I'm new to javascript and css.
The program was developed in .net vistual studio.
The problem is this: I have a page that has a map where I make a circle in a region of it. The behavior the system should have is when I click the circle button, the system should open a form with information from the region where I made the circle. However, when I expand the map, the form is hidden behind the map. Can anyone tell me how I can bring this form forward in the expanded map form? In the attached image, the window behind the map appears in blue.
click to see map image
function configPontosMapa(sender, args) {
var label, marker, dataItem, location, circle, coordenadas, polygon, tableView, lats,
lngs, idPonto, nome, barra, shape, idPtoGlobalAux;
var dataItems = $find(gridPontos).get_masterTableView().get_dataItems();
var latlngBounds = new google.maps.LatLngBounds();
mapa.ClearMap();
MapaLabel.ClearLabels();
clearMapaBotao();
clearMapaBotaoSubPonto();
for (var i = 0; i < dataItems.length; i++) {
dataItem = dataItems[i];
idPonto = dataItem.getDataKeyValue("IdPontoGeografico");
idPtoGlobalAux = dataItem.getDataKeyValue("IdPontoGlobal");
nome = dataItem.getDataKeyValue("Nome");
lats = dataItem.getDataKeyValue("LatitudesFormatadas").split('|');
lngs = dataItem.getDataKeyValue("LongitudesFormatadas").split('|');
if (lats.length == 1) {
location = new google.maps.LatLng(parseFloat(lats[0]), parseFloat(lngs[0]));
var raio = parseFloat(dataItem.getDataKeyValue("Raio"));
if (!raio) {
raio = 1;
}
circle = new google.maps.Circle({
center: location,
radius: raio,
strokeColor: corPadrao,
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: corPadrao,
fillOpacity: 0.15,
map: mapa.Mapa,
entity: idPonto,
idPontoGlobal: idPtoGlobalAux,
zIndex: 0
});
if (idPtoGlobalAux) {
barra = new MapaBarraBotao(mapa.Mapa, circle.getCenter(), circle, showModalPontoGlobal);
}
else {
barra = new MapaBarraBotao(mapa.Mapa, circle.getCenter(), circle, showModalNovoPonto);
}
circle.barraBotao = barra;
shape = circle;
mapa.NewCircleByShape(circle);
latlngBounds.union(circle.getBounds());
marker = mapa.NewMarker();
marker.bindTo('position', circle, 'center');
marker.setOptions({ ponto: circle, title: nome });
marker.setIcon('../../../Images/Ponto/MarcadorPonto1.png');
//label.bindEvents(marker);
circle.setEditable(true);
circle.barraBotao.ocultaBotaoSalvarCancelar();
google.maps.event.addListener(circle, 'rightclick', function () {
novoSubponto(this);
});
google.maps.event.addListener(circle, 'center_changed', function () {
this.setOptions({ fillColor: corAlterado, strokeColor: corAlterado });
this.barraBotao.draw(this.getCenter());
});
google.maps.event.addListener(circle, 'radius_changed', function () {
this.setOptions({ fillColor: corAlterado, strokeColor: corAlterado });
});
} else {
coordenadas = [];
for (var j = 0; j < lats.length; j++) {
coordenadas[j] = Mapa.NewLatLng(parseFloat(lats[j]), parseFloat(lngs[j]));
}
latlngBounds.extend(coordenadas[0]);
polygon = mapa.NewPolygonByPaths(coordenadas);
polygon.setEditable(true);
polygon.getPath().obj = polygon;
if (idPtoGlobalAux) {
barra = new MapaBarraBotao(mapa.Mapa, polygon.getPath().getAt(0), polygon, showModalPontoGlobal);
}
else {
barra = new MapaBarraBotao(mapa.Mapa, polygon.getPath().getAt(0), polygon, showModalNovoPonto);
}
polygon.barraBotao = barra;
shape = polygon;
polygon.setOptions({
entity: idPonto,
idPontoGlobal: idPtoGlobalAux,
barraBotao: barra,
zIndex: 0
});
marker = mapa.NewMarkerAtPoint(coordenadas[0]);
marker.setOptions({ ponto: polygon, title: nome });
marker.setIcon('../../../Images/Ponto/MarcadorPonto1.png');
polygon.barraBotao.ocultaBotaoSalvarCancelar();
polygon.marker = marker;
google.maps.event.addListener(polygon.getPath(), 'set_at', function () {
var coord = this.getAt(0);
this.obj.setOptions({ fillColor: corAlterado, strokeColor: corAlterado });
this.obj.barraBotao.draw(coord);
this.obj.label.draw(coord);
this.obj.marker.setPosition(coord);
});
google.maps.event.addListener(polygon.getPath(), 'insert_at', function () {
this.obj.setOptions({ fillColor: corAlterado, strokeColor: corAlterado });
this.obj.barraBotao.draw(this.getAt(0));
});
google.maps.event.addListener(polygon, 'rightclick', function () {
novoSubPoligono(this);
});
}
google.maps.event.addListener(marker, 'click', function () {
mapa.Mapa.setCenter(this.getPosition());
mapa.Mapa.setZoom(15);
});
if (idPonto == 0) {
label = createLabel(dataItem.getDataKeyValue("Nome"), null, shape, showModalPontoGlobal);
}
else {
label = createLabel(dataItem.getDataKeyValue("Nome"), null, shape);
}
label.bindEvents(marker);
shape.label = label;
arrayBotao.push(barra);
}
mapa.SetBoundsCircle(latlngBounds);
}
If this form has position prop then you can add z-index to this element.
z-index: 10 should do.
Is their a way to get latitude and longitude of polyline?
var firstpolyline = new L.Polyline(pointList, {
color: 'black',
opacity: 5,
smoothFactor: 1,
weight: 3,
})
map.addLayer(firstpolyline);
firstpolyline.getLatLng();
here firstpolyline is givng an error that "getLatLng() is not a function". I want to check if polyline is within the map bound or not like this
var bounds = map.getBounds();
if(bounds.contains(firstpolyline.getLatLng())){
......
}
You have to use getLatLngs() function. So try this:
var firstpolyline = new L.Polyline(pointList, {
color: 'black',
opacity: 5,
smoothFactor: 1,
weight: 3,
})
map.addLayer(firstpolyline);
var arrayOfPoints = firstpolyline.getLatLngs();
Then you can easily iterate over an array of points and get latitude and logitude or check if point is in bounds of polygon.
for(var i=0; i < arrayOfPoints.length; i++) {
if(map.getBounds().contains(arrayOfPoints[i])) {
console.log('is in bounds');
};
}
I'm trying to, given a .json containing a lot of points, determine how many there are in each region (probably returning a dictionary), which are defined in another .json file.
I'm doing this based on this example:
https://www.mapbox.com/mapbox.js/example/v1.0.0/point-in-polygon/
However, I can't get it to work.
This line:
var layer = leafletPip.pointInLayer(this.getLatLng(), states, true);
Returns empty for my test case.
Here is a jsfiddle reproducing my code:
http://jsfiddle.net/Pe5xU/346/
map = L.map('map').setView([40.658528, -73.952551], 10);
// Load a tile layer
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data © OpenStreetMap',
maxZoom: 18,
minZoom: 10
}).addTo(map);
geojson = L.geoJson(data).addTo(map);
var all_markers = [];
var layers = {};
$.each(dots, function(index, rec) {
var markers = {}
if (rec.hasOwnProperty("latitude") && rec.hasOwnProperty("longitude")) {
var marker = L.circleMarker([rec.latitude, rec.longitude], marker_style()).addTo(map);
all_markers.push(marker);
}
});
var all_layers = L.featureGroup(all_markers);
map.fitBounds(all_layers.getBounds());
function marker_style() {
return {
radius: 4,
weight: 0,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.7
};
}
$.each(dots, function(index, rec) {
if (rec.hasOwnProperty("latitude") && rec.hasOwnProperty("longitude")) {
var layer = leafletPip.pointInLayer([rec.latitude, rec.longitude], geojson, true);
console.log(layer);
}
});
This code example provides coordinates in latitude, longitude order. As documented in the leaflet-pip readme, leaflet-pip expects coordinates in longitude, latitude order, the same as GeoJSON and other geospatial formats.
All. I'm developing dashboard application which uses google maps API. I'm trying to render many google.maps.Polygon in a map.
Once it loads polygon data from AJAX request, I created some polygons, and I store them in array. For each loop of creating polygon,
I added google maps event to every polygon (mouseover, mouseout, and click event). It succesfully rendered all polygon on the map. But
not all polygon has event, just some of them. Would you like to give me some solutions of this problem?
Here is the part of code
function big_loadMapCells() {
var serviceUrl = './Services/example';
var currentIdx = 0;
var pagingCount = 5000;
while (currentIdx < totalCount) {
// send ajax
Ext.Ajax.request({
method: "GET",
url: serviceUrl + '?start=' + currentIdx + '&limit=' + pagingCount,
timeout: 300000,
success: function (c) {
var jsonObj = Ext.JSON.decode(c.responseText);
if (jsonObj) {
big_createCellsFromJSON(jsonObj);
}
}
});
currentIdx += pagingCount;
}
}
function big_createCellsFromJSON(jsonObj) {
// looping for creating polygon
for (var a = 0; a < jsonObj.items.length; a++) {
var cellJson = jsonObj.items[a];
var data = {
lacCi: cellJson.LACCI
tech: cellJson.TECH,
periodType: cellJson.PERIOD_TIME,
time: cellJson.DATETIME_ID,
region: cellJson.REGION,
latitude: cellJson.LATITUDE,
longitude: cellJson.LONGITUDE,
node: cellJson.NODE,
siteName: cellJson.SITE,
kpi: cellJson.KPI,
cellName: cellJson.CELL_NAME,
azimuth: cellJson.AZIMUTH,
beamWidth: width,
beamConst: radius,
color: cellJson.COLOR
};
var myCell = big_createCellPolygon(data);
big_arrCells.push(myCell);
}
}
function big_createCellPolygon(data) {
// create polygon using my own javascript, CELL object
var myCell = new CELL();
myCell.setOptions({
paths: myCell.pts,
strokeColor: myCell.color,
strokeOpacity: 0.8,
strokeWeight: 0,
fillColor: myCell.color,
fillOpacity: 0.5,
map: big_map
});
function addCellEvent(myCell) {
google.maps.event.addListener(myCell, 'mouseover', function () {
this.setOptions({
strokeWeight: 1,
fillOpacity: 0.7
});
});
google.maps.event.addListener(myCell, 'mouseout', function () {
this.setOptions({
strokeWeight: 0,
fillOpacity: 0.5
});
});
google.maps.event.addListener(myCell, 'click', function (evt) {
big_createInfoWindowCell(data, evt.latLng);
});
}
addCellEvent(myCell);
return myCell;
}
big_loadMapCells();