OpenLayers time to layer (time control) - javascript

I am new to OpenLayers and I would like to have something takes (date+time) and to get (layer) on the map
E.g I have layers for the Weather in (15.02.2010), (16.02.2010) and so on.
for example.. user enter (date+time) and the result (layer of the same date on the map)
Are there any ideas? Example? API!

Adapted from the OpenLayers example:
<input type="text" name="customParam" id="customParam">
<button onclick="showIt()">show it</button>
<script>
let source = null;
const map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
function showIt() {
const customParam = document.getElementById("customParam").value;
const isNew = (!source);
if(isNew) {
source = new ol.source.XYZ();
}
source.setUrl(`https://{a-c}.MY-TILES.com/{z}/{x}/{y}.png?myTimeParam=${customParam}`);
source.refresh();
if(isNew) {
map.addLayer(new ol.layer.Tile({ source: source }));
}
}
</script>

Related

How to make a popup with GET/POST request ASP NET CORE

I have a map, with n numbers of markers with a unique ID. When I click on them a custom popup for that marker appears (using JS and CSS). Every time I click on one of the markers, I want it to send a POST request that will change the URL from ~/reports/index to ~report/index/custom_Id. I need it to be with a custom id in the URL because I need to load some popups from another page using GET request.
My code:
Load map:
<script type="text/javascript">
var layers = [new ol.layer.Tile({ source: new ol.source.OSM() })];
var map = new ol.Map({
target: 'map',
view: new ol.View({
zoom: 5,
center: [166326, 5992663]
}),
interactions: ol.interaction.defaults({ altShiftDragRotate: false, pinchRotate: false }),
layers: layers
});
const options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
};
function togglePopup(id) { //The function that revals the popup
document.getElementById("overlay-container-" + id).classList.toggle("active");
}
// Vector Feature Popup logic
map.on('click', function (e) { //The "sensor" that detects if a marker has been clicked.
map.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
togglePopup(feature.getId());
resetCurrent();
handleImages(feature.getId());
})
})
Add markers (this is inside a bigger for loop):
<script type="text/javascript">
markers = new ol.layer.Vector({
source: new ol.source.Vector(),
style: new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1],
src: 'https://ucarecdn.com/4b516de9-d43d-4b75-9f0f-ab0916bd85eb/marker.png' // => https://app.uploadcare.com/projects/c05bbeb5e1a61e862903/files/7110cd57-b0ee-4833-bcd1-ff0343dd01cc/?limit=100&ordering=-datetime_uploaded
})
})
});
map.addLayer(markers);
var marker = new ol.Feature(new ol.geom.Point([parseFloat(#_Data.coordLat), parseFloat(#_Data.coordLong)]));
marker.setId(#_Data.Id);
markers.getSource().addFeature(marker);
</script>
I know that if it was a HTML button for something like that I could have add asp-route-id=#_Data.Id or something but this is JS. How can I make it?

Pass json data to JavaScript without creating new object

I am querying json data from database then performing some filtering and further procedures. After that I want to display that data on map, so I am passing it through JSInterop to JavaScript. Everything seems to be working except that on each method execution I am getting new map on my webpage. So after executing method 4 times, I am having 4 maps on web page.
Please comment, if additional code is necessary...
Index.razor:
<div>
<select id="layer-select" style="visibility:hidden;">
<option value="osm" selected>Open Street Map</option>
</select>
<div class="card-body p-0">
<div id="map"></div>
<div id="popup" class="ol-popup">
<div id="popup-content"></div>
</div>
</div>
</div>
Index.razor.cs:
[Inject] IJSRuntime JSRuntime { get; set; }
...
private async Task UpdateData()
{
this.SelectedDate = this.SelectedDate.Value.AddDays(1);
this.FilteredDataRecords = this.DataRecords
.Where(w => w.TimeNow.Date == SelectedDate.Value.Date && (w.Latitude != 0 || w.Longitude != 0))
.OrderBy(o => o.TimeNow)
.ToList();
string jsonData = JsonSerializer.Serialize(this.FilteredDataRecords);
await JSRuntime.InvokeAsync<object>("olMap.showMap", jsonData);
}
map.js:
window.olMap = {
showMap: function (jsonData) {
var HereLayers = [
{
base: 'base',
type: 'maptile',
scheme: 'osm',
},
];
...
var vectorLayer = new ol.layer.Vector({
source: loadMarineData(JSON.parse(jsonData)), //JSON.parse(jsonData)
visible: true,
style: new ol.style.Style({
stroke: new ol.style.Stroke({ color: '#d12710', width: 4 })
})
});
var map = new ol.Map({
overlays: [overlay],
target: 'map',
layers: layers,
view: new ol.View({
center: ol.proj.fromLonLat([25.2849, 60.0917]),
zoom: 8
})
});
map.addLayer(vectorLayer);
map.addLayer(nauticLayer);
....
var select = document.getElementById('layer-select');
function onChange() {
var scheme = select.value;
for (var i = 0, ii = layers.length; i < ii; ++i) {
layers[i].setVisible(HereLayers[i].scheme === scheme);
}
}
select.addEventListener('change', onChange);
onChange();
}
};
i've not used this map engine before but i would suggest
var map = new ol.Map({
overlays: [overlay],
target: 'map',
layers: layers,
view: new ol.View({
center: ol.proj.fromLonLat([25.2849, 60.0917]),
zoom: 8
})
});
should be
if(! document.map){
document.map = new ol.Map({
overlays: [overlay],
target: 'map',
layers: layers,
view: new ol.View({
center: ol.proj.fromLonLat([25.2849, 60.0917]),
zoom: 8
})
});
}
const map = document.map
this basically says get the already created map and only create a new map it if doesn't exist
just remember that because you are using the same map over and over again you will need to clean up the previous runs yourself
ie before
map.addLayer(vectorLayer);
map.addLayer(nauticLayer
do
for(const layer of map.getLayers())
{
map.removeLayer(layer)
}
(note this is example code to demonstrate the idea, not functioning code)
you should also avoid the var keyword instead you should use const and let var is a hold over from the early days of JS before the introduction of scoping and it has some nasty side effects if you use it in the wrong way

how to change the default marker OPENLAYERS 5

I am trying to display some markers on the OSM. This works so far, but i just wanted to change the default marker against another one from a local path, but i didnt know how to add this to my code, i have tried the setStyle but i didnt know how to apply it correctly. It would be also nice if am able to style the icon too.
I also want markers to be dynamically displayed, because i am doing this manually each time through
var layer = new ol.layer.Vector({source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([4.35247, 50.84673]))
}),
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([4.35247, 52.84673]))
}),
]
});
Here is a snippet of the full code that i use
/* open street map newest version */
var map = new ol.Map({
target: 'map', // the div id
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([4.35247, 52.520008]),
zoom: 4
})
});
// add a marker to the map
var layer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([4.35247, 50.84673]))
}),
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([4.35247, 52.84673]))
})
]
})
});
map.addLayer(layer);
//initialize the popup
var container = document.getElementById('popup');
var content = document.getElementById('popup-content');
var overlay = new ol.Overlay({
element: container,
autoPan: true,
autoPanAnimation: {
duration: 250
}
});
map.addOverlay(overlay);
//display the pop with on mouse over
map.on('pointermove', function (event) {
if (map.hasFeatureAtPixel(event.pixel) === true) {
var coordinate = event.coordinate;
content.innerHTML = '<b>Hello world!</b><br />I am a popup.';
overlay.setPosition(coordinate);
}
else {
overlay.setPosition(undefined);
closer.blur();
}
});
Fixed this, the issue was from the local path. If this may help anyone i added this to my code
layer.setStyle(new ol.style.Style({
image: new ol.style.Icon({
src: 'https://wiki.openstreetmap.org/w/images/0/0c/Hgv.png'
})
}));

I want to have some coordinates on my openlayer map

i am trying to get some Dots on my Map with Openlayer. The Maps works fine. I got a JSON file with longitude and latitude and i want them to appear on my map. But it is not working. the parsing wont work somehow.
Error 1:
Error 2:
JSON file: https://github.com/CodeforChemnitz/Haltestellen/blob/gh-pages/haltestellen.json
My Code:
<div class="main-container-cvag">
<div id="map" class="map"></div>
<script src="https://openlayersbook.github.io/openlayers_book_samples/assets/ol3/js/ol.js"></script>
<script>
// Declare a Tile layer with an openstreetmap
var osmLayer = new ol.layer.Tile({
source: new ol.source.OSM()
});
// latitude and longitude to Chemnitz projection
var chemnitz = ol.proj.transform([12.9213697, 50.827845], 'EPSG:4326', 'EPSG:3857');
// Create a View, set it center and zoom level
var view = new ol.View({
center: chemnitz,
zoom: 13
});
//source
var chemnitzStationSource = new ol.source.Vector();
//dot style
function dotstyle(feature) {
var style = new ol.style.Style({
image: new ol.style.Circle({
radius: 6,
stroke: new ol.style.Stroke({
color: 'white',
width: 2
}),
fill: new ol.style.Fill({
color: 'green'
})
})
});
return [style];
}
//new layer
var chemnitzStations = new ol.layer.Vector({
source: chemnitzStationSource,
style: dotstyle
})
//new Map
var map = new ol.Map({
target: 'map',
layers: [osmLayer, chemnitzStations],
view: view
});
$.ajax({
url: "haltestellen.json",
dataType: "jsonp",
crossDomain: true,
success: function(data) {
var transform = ol.proj.getTransform('EPSG:4326', 'EPSG:3857');
data.items.forEach(function (item) {
var feature = new ol.Feature(item);
feature.set('url', item.stations);
var coordinate = transform([parseFloat(item.longitude), parseFloat(item.latitude)]);
var geometry = new ol.geom.Point(coordinate);
feature.setGeometry(geometry);
chemnitzStationSource.addFeature(feature);
console.log(parseFloat(item.longitude));
});
}
});
map.addLayer(osmLayer);
// Set the view for the map
map.setView(view);
</script>
</div>
Can someone help me what to do? :)
You are loading JSON, but have dataType: "jsonp".
Change it to dataType: "json",.

Delete VectorLayer

I am trying to delete VectorSource Layer for redraw markers. The problem is that when I execute a setInterval function every 3 seconds, the new markers overlap to previous markers. The previous markers are not deleted.
I am trying with
map.getLayers().item(1).getSource().clear();
map.getLayers().item(1).getSource().getSource().clear();
But it not work.
So:
Mi code is:
var vectorSource = new ol.source.Vector({
features: iconFeatures //add an array of features
});
var clusterSource = new ol.source.Cluster({
source: vectorSource,
distance: 40
});
var vectorLayer = new ol.layer.Vector({
source: clusterSource,
style: clusterStyle
});
// Maps
var map = new ol.Map({
controls: ol.control.defaults({
attributionOptions: /** #type {olx.control.AttributionOptions} */ ({
collapsible: false
})
}),
target: 'map', // The DOM element that will contains the map
renderer: 'canvas', // Force the renderer to be used
layers: [
// Add a new Tile layer getting tiles from OpenStreetMap source
new ol.layer.Tile({
source: new ol.source.OSM()
//source: new ol.source.OSM({
//crossOrigin: null,
//url: 'http://34.240.39.198/osm_tiles/{z}/{x}/{y}.png',
//}),
}),
vectorLayer,
],
// Create a view centered on the specified location and zoom level
view: new ol.View({
center: ol.proj.transform([-3.7467975, 40.3705281], 'EPSG:4326', 'EPSG:3857'),
zoom: 3,
maxZoom: 15,
minZoom:2,
//extent: [226838, 5084100, 255700, 5055200],
}),
/*interactions: ol.interaction.defaults({
dragPan: false
}),*/
});
And function for Redraw is:
function get_traces(){
var token = $('meta[name="csrf-token"]').attr('content');
$.ajax({
type: "post",
url: "device_mapA",
typeData:'JSON',
data: {
'_method': 'POST',
'_token': token,
}, success: function (showdevice) {
removeAllMarkers();
iconFeatures = [];
showdevice[0].forEach(function(index) {
changeMarker(showdevice[0]); //this function redraw iconFeatures array correctly.
});
});
// console.log(iconFeatures);
var vectorSource = new ol.source.Vector({
features: iconFeatures //add an array of features
});
var clusterSource = new ol.source.Cluster({
source: vectorSource,
distance: 40
});
var vectorLayer = new ol.layer.Vector({
// source : vectorSource,
source: clusterSource,
style: clusterStyle
});
map.getLayers().item(1).getSource().clear();
map.getLayers().item(1).getSource().getSource().clear();
map.addLayer(vectorLayer);
map.getLayers().item(1).getSource().clear();
//console.log(map.getLayers().item(1).getSource()); It not working neither.
}
It does not actually abort those 7 iterations, it just skips those array items.
In your forEach cycle there is an array of references to map layers. If you take an element of that array (reference is "layer") and you remove it from map as it is, you remove the reference, so it is neither in the map nor in your array anymore and accidentally there is another reference on that index.
So if you have array:
0: layer0, name "layer0"
1: layer1, name "layer1"
2: layer2
after this forEach there will remain
0: layer1, name "layer1"
1: layer2
because after removal layer0, there is layer1 on the index 0 and AFTER that forEach moves along (to index 1), where it already finds layer without name.
To solve that, just use functions getArray() and slice() (to duplicate the reference array), something like that:

Categories

Resources