How to style KML? - javascript

I have added drag and drop to my map, based on https://openlayers.org/en/latest/examples/drag-and-drop.html. Styling works for f.i. gpx but fails for kml.
Whatever I try, I can't get the kml features styled the way I want. Kml files with a style included are shown using that style but I cannot replace the style with my style. Kml with points but without a style are shown using a terrible old Google style push pin.
var styleFunction = function (feature, resolution) {
console.log("in styleFunction()");
var featureStyleFunction = feature.getStyleFunction();
if (featureStyleFunction) {
return featureStyleFunction.call(feature, resolution);
} else {
return defaultStyle[feature.getGeometry().getType()];
}
};
var dragAndDropInteraction = new ol.interaction.DragAndDrop({
formatConstructors: [
ol.format.GeoJSON,
ol.format.TopoJSON,
ol.format.EsriJSON,
ol.format.IGC,
ol.format.GPX,
ol.format.KML
]
});
map.addInteraction(dragAndDropInteraction);
dragAndDropInteraction.on('addfeatures', function (event) {
console.log("in dragAndDropInteraction");
const ext = event.file.name.split('.').pop().toLowerCase();
console.log(" ext: " + ext);
let vectorSource;
let layer;
switch (ext) {
case 'gpx':
vectorSource = new ol.source.Vector({
features: event.features,
format: new ol.format.GPX(),
// readExtensions:
});
break;
case 'kml':
vectorSource = new ol.source.Vector({
features: event.features,
format: new ol.format.KML({
extractStyles: false,
// showPointNames: false,
// extractAttributes: true,
// writeStyles: false
}),
});
break;
default:
break;
}
if (vectorSource) {
map.addLayer(new ol.layer.Vector({
source: vectorSource,
style: styleFunction
}));
map.getView().fit(vectorSource.getExtent());
}
An example at jsfiddle
Thanks.

Related

FeatureLoader not loading features in OpenLayers

Trying to use a featureLoader in OpenLayers 6 so that I can gain access to the featuresloadend event but when I try to load the features nothing shows up. Further examination of the pointLayer shows that no features had been added to the Layer.
const pointSource = new ol.source.Vector({
format: new ol.format.GeoJSON(),
loader: function(extent, resolution, projection, success, failure) {
var proj = projection.getCode();
var url = '/awdndb/monitor/geoawdndata?product=scqc1440&begin=2022-09-20&end=2022-09-20&sensor=AirTempMax2m&units=si';
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
var onError = function() {
vectorSource.removeLoadedExtent(extent);
failure();
}
xhr.onerror = onError;
xhr.onload = function() {
if (xhr.status == 200) {
var features = pointSource.getFormat().readFeatures(JSON.parse(xhr.responseText));
pointSource.addFeatures(features);
success(features);
}
else {
onError();
}
}
xhr.send();
}
})
const pointLayer = new ol.layer.Vector({
source: pointSource,
title: 'pointLayer',
style: pointFunction
});
//Setup Overlay
const overlay = new ol.Overlay({
element: container,
autoPan: true,
autoPanAnimation: {
duration: 250
}
});
//Setup Map Object
const map = new ol.Map({
target: 'map',
overlays: [overlay],
view: new ol.View({
center: [-10997148, 4569099],
zoom: 5
})
});
map.addLayer(baseLayer);
map.addLayer(pointLayer);
the json far to big to include entire code):
{"type":"FeatureCollection","crs":{"type":"name","properties":{"name":"EPSG:4326"}},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-94.98,48.86]},"properties":{"name":"Williams 6N","state":"MN","county":"Lake of the Woods","sensors":["TIMESTAMP","AirTempMax2m","AirTempMax2m_SCQC_Flag"],"units":["TS","C","Flag"],"data":[["2022-09-20",20.58," "]]}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-100.61,38.51]},"properties":{"name":"Lane","state":"KS","county":"Lane","sensors":["TIMESTAMP","AirTempMax2m","AirTempMax2m_SCQC_Flag"],"units":["TS","C","Flag"],"data":[["2022-09-20",37.86," "]]}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-96.59,39.21]},"properties":{"name":"Manhattan","state":"KS","county":"Riley","sensors":["TIMESTAMP","AirTempMax2m","AirTempMax2m_SCQC_Flag"],"units":["TS","C","Flag"],"data":[["2022-09-20",37.46," "]]}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-108.72,37.53]},"properties":{"name":"Yellow Jacket","state":"CO","county":"Montezuma","sensors":["TIMESTAMP","AirTempMax2m","AirTempMax2m_SCQC_Flag"],"units":["TS","C","Flag"],"data":[["2022-09-20",24.62," "]]}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-102.57,48.49]},"properties":{"name":"Powers Lake 6SE","state":"ND","county":"Mountrail","sensors":
...

Using local GEOJson with OpenLayers

I am a relative beginner to using OpenLayers so I was playing around with some of the examples given on the OpenLayers website. When trying the image-vector-layer example, I had a problem where it would work fine with a json online, but when using a local geojson file the response under the networks section for the geojson file would be an html instead, giving the error "Unexpected token < in JSON at position 0". Attached is my javascript below, the error is occurring at the "url: data/countries.geojson". Is there any way I can use a local file instead of an online link? Thank you!
import 'ol/ol.css';
import GeoJSON from 'ol/format/GeoJSON';
import Map from 'ol/Map';
import VectorImageLayer from 'ol/layer/VectorImage';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import View from 'ol/View';
import {Fill, Stroke, Style} from 'ol/style';
const style = new Style({
fill: new Fill({
color: '#eeeeee',
}),
});
const vectorLayer = new VectorImageLayer({
background: 'lightblue',
imageRatio: 2,
source: new VectorSource({
url: 'data/countries.geojson',
format: new GeoJSON(),
}),
style: function (feature) {
const color = feature.get('COLOR') || '#eeeeee';
style.getFill().setColor(color);
return style;
},
});
const map = new Map({
layers: [vectorLayer],
target: 'map',
view: new View({
center: [0, 0],
zoom: 1,
}),
});
const featureOverlay = new VectorLayer({
source: new VectorSource(),
map: map,
style: new Style({
stroke: new Stroke({
color: 'rgba(255, 255, 255, 0.7)',
width: 2,
}),
}),
});
let highlight;
const displayFeatureInfo = function (pixel) {
const feature = map.forEachFeatureAtPixel(pixel, function (feature) {
return feature;
});
const info = document.getElementById('info');
if (feature) {
info.innerHTML = feature.get('ECO_NAME') || ' ';
} else {
info.innerHTML = ' ';
}
if (feature !== highlight) {
if (highlight) {
featureOverlay.getSource().removeFeature(highlight);
}
if (feature) {
featureOverlay.getSource().addFeature(feature);
}
highlight = feature;
}
};
map.on('pointermove', function (evt) {
if (evt.dragging) {
return;
}
const pixel = map.getEventPixel(evt.originalEvent);
displayFeatureInfo(pixel);
});
map.on('click', function (evt) {
displayFeatureInfo(evt.pixel);
});

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'
})
}));

kml style on draganddrop and ol.interactionSelect

With ol 4.4.2 kml style with drag and drop is very difficult and I can't set it by the layer style.
I can style it through the feature, but when I do, it's the style of the select interaction that does not work anymore.
The extractStyle: false does not work anymore.
Is there a bug ?
How can I do it ?
dragAndDropInteraction.on('addfeatures', function(e) {
var vectorSource = new ol.source.Vector({
opacity: 1,
features: new ol.Collection(),
format: new ol.format.KML({
extractStyles: false, defaultStyle: AnnotImportStyle
}),
visible: true
});
var features = e.features;
//features.forEach (function(s){s.setStyle(AnnotImportStyle)}); it works but put the style of select out
vectorSource.addFeatures(features);
var file_name = e.file.name;
var name = file_name.substr(0, file_name.lastIndexOf('.'));
var vector = new ol.layer.Vector({
title: name,
source: vectorSource,
style: AnnotImportStyle,
visible: true,
});
map.addLayer(vector);
map.getView().fit(vectorSource.getExtent());
});

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