openlayers markers with popup - javascript

I am trying to display a map with markers. I want the ability to click these markers such that extra information can be displayed (similiar to the way it works in google earth). I have the map and the markers (or features) but can not get the "popup" with extra information to work.
The JS:
function init(){
var northSeaLonLat = [4.25, 52.05];
var centerWebMercator = ol.proj.fromLonLat(northSeaLonLat);
var tileLayer = new ol.layer.Tile({ source: new ol.source.OSM() });
markerLayer = new ol.layer.Vector({ source: new ol.source.Vector({ features: [], projection: 'EPSG:3857' }) });
var map = new ol.Map({
controls: ol.control.defaults().extend([
new ol.control.MousePosition({
coordinateFormat: ol.coordinate.createStringXY(3),
projection: 'EPSG:4326',
undefinedHTML: ' ',
className: 'custom-mouse-position',
target: document.getElementById('custom-mouse-position'),
})
]),
layers: [tileLayer, markerLayer],
target: 'map',
view: new ol.View({
projection: 'EPSG:3857',
center: centerWebMercator,
zoom: 7
})
});
// Add marker
var circle = new ol.style.Style({
image: new ol.style.Circle({
radius: 4,
fill: new ol.style.Fill({
color: 'rgba(200,0,0,0.9)',
}),
stroke: new ol.style.Stroke({
color: 'rgba(100,0,0,0.9)',
width: 2
})
})
});
coordinates = [[4.25, 52.05], [4.21, 52.01], [4.29, 52.29], [5.25, 52.05], [4.25, 51.05]];
for (i = 0; i < coordinates.length; i++) {
var feature = new ol.Feature(
new ol.geom.Point(ol.proj.transform(coordinates[i], 'EPSG:4326', 'EPSG:3857'))
);
feature.description = 'Coordinates: '+coordinates[i][0]+','+coordinates[i][1]+'\nBla';
feature.setStyle(circle);
markerLayer.getSource().addFeature(feature);
}
var element = document.getElementById('popup');
var popup = new ol.Overlay({
element: element,
positioning: 'bottom-center',
stopEvent: false
});
map.addOverlay(popup);
// display popup on click
map.on('click', function(evt) {
var feature = map.forEachFeatureAtPixel(evt.pixel,
function(feature, layer) {
return feature;
});
if (feature) {
popup.setPosition(evt.coordinate);
$(element).popover({
'placement': 'top',
'html': true,
'content': feature.get('description')
});
$(element).popover('show');
} else {
$(element).popover('destroy');
}
});
}
The code I got from an example on the website: http://openlayers.org/en/v3.11.1/examples/icon.html
It works there but I can't get my version to work. Any idea why?

popover isn't part of OpenLayers but contained in Bootstrap: http://getbootstrap.com/javascript/#popovers
Also see the OpenLayers example on overlays: https://openlayers.org/en/latest/examples/overlay.html

Related

rendering opensensemap IDW features via openlayers

I'm trying to render some extra features on map using openlayers. The features can be fetched from the opensensemap API, but for some reason they are not rendered. As I am completely new to openlayers, and dont know much javascript either, I hope for some help.
live code: https://ttnkn.github.io/map/pax/
var GeoStyle = {
'Point': new ol.style.Style({
image: new ol.style.Icon({
src: '../img/bike.png',
scale: 0.075,
})
}),
'Circle': new ol.style.Circle({
fill: new ol.style.Fill({
color: 'rgba(255,255,255,0.4)'
}),
stroke: ol.style.Stroke({
color: '#3399CC',
width: 1.25
}),
radius: 5
})
};
function GeoStyleFunc (feature,resolution) {
return GeoStyle[feature.getGeometry().getType()];
}
var VectorSource = new ol.source.Vector({
format: new ol.format.GeoJSON(),
url: 'https://api.opensensemap.org/boxes?bbox=9.118815,47.653129,9.228427,47.698786&format=geojson&exposure=mobile',
});
var VectorTile = new ol.source.XYZ({
url: 'http://tile.memomaps.de/tilegen/{z}/{x}/{y}.png ',
attributions: 'Map © OSM | Tiles © MeMoMaps | Data © OpenSenseMap'
});
var map = new ol.Map({
target: document.getElementById('map'),
layers: [
new ol.layer.Tile({
source: VectorTile
}),
new ol.layer.Vector({
source: VectorSource,
style: GeoStyleFunc
})
],
controls: ol.control.defaults({ zoom: true, attribution: true }),
view: new ol.View({
center: ol.proj.fromLonLat([9.173, 47.672]),
zoom: 15,
maxZoom: 17,
minZoom: 13
})
});
var url = 'https://api.opensensemap.org/statistics/idw?bbox=9.118815,47.653129,9.228427,47.698786&phenomenon=Temperatur&gridType=hex&cellWidth=2';
fetch(url).then(value => {
value.json().then(value => {
var featureJson = value.data.featureCollection;
var features = (new ol.format.GeoJSON()).readFeatures(featureJson);
var vectorSourceHEX = new ol.source.Vector({
features: features,
projection: ol.proj.get('EPSG:4326')
});
var vectorLayer = new ol.layer.Vector({
source: vectorSourceHEX,
// style: GeoStyleFunc
});
map.addLayer(vectorLayer);
});
}, error => { console.log(error) });
The projection option isn't used in vector sources. If you use readFeatures you must transform the data to the view projection (when you construct a source with a url that is done automatically).
var features = (new ol.format.GeoJSON()).readFeatures(featureJson, {
dataProjection: 'EPSG:4326',
featureProjection: map.getView().getProjection()
});
var vectorSource = new ol.source.Vector({
features: features,
});

how to add lines between point in openlayers

I'm trying to add a line between two points on my map. I have the following code but the web page only shows me a base map without the line that I want.
How do I add this line to an OpenLayers map?
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([ -95.36,29.75]),
zoom: 10
})
});
var coords = [[-95.36,29.75], [-96.36,30.75]];
var lineString = new ol.geom.LineString(coords);
// transform to EPSG:3857
lineString.transform('EPSG:4326', 'EPSG:3857');
// create the feature
var feature = new ol.Feature({
geometry: lineString,
name: 'Line'
});
var lineStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 10
})
});
var raster = new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'sat'})
});
var source = new ol.source.Vector({
features: [feature]
});
var vector = new ol.layer.Vector({
source: source,
style: [lineStyle]
});
map.addLayer(vector);
</script>
`
Your code contains a javascript error in OpenLayers v5.x (and v4.6.5, which doesn't appear in v3.16.0):
Uncaught TypeError: ol.source.MapQuest is not a constructor
Remove the code that specifies that:
var raster = new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'sat'})
});
and the line displays.
proof of concept fiddle
code snippet:
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([-95.36, 29.75]),
zoom: 10
})
});
var coords = [
[-95.36, 29.75],
[-96.36, 30.75]
];
var lineString = new ol.geom.LineString(coords);
// transform to EPSG:3857
lineString.transform('EPSG:4326', 'EPSG:3857');
// create the feature
var feature = new ol.Feature({
geometry: lineString,
name: 'Line'
});
var lineStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 10
})
});
var source = new ol.source.Vector({
features: [feature]
});
var vector = new ol.layer.Vector({
source: source,
style: [lineStyle]
});
map.addLayer(vector);
html,
body,
#map {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px;
}
<link rel="stylesheet" href="https://openlayers.org/en/v5.2.0/css/ol.css" type="text/css">
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.2.0/build/ol.js"></script>
<div id="map" class="map"></div>

How to change a open layer tile source?

I need to change the layer source for openlayer (using open weather api). Currently I am using the following code with no success.
let layer = this.map.getLayers().getArray()[2]
layer.setSource(forecastLayer)
Could you tell me what I am doing wrong?
What is the correct way to update the data source?
renderMapOpenLayer () {
let geo = this.props.geo
// render marker vector
let markerFeature = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.transform([-72.0704, 46.678], 'EPSG:4326', 'EPSG:3857')) // TODO // take lat long from openweather api which should be sotred in the state
})
let markerSource = new ol.source.Vector({
features: [markerFeature]
})
let markerStyle = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0, 0],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
opacity: 0.75,
src: 'assets/pin.svg'
}))
})
let markerLayer = new ol.layer.Vector({
source: markerSource,
style: markerStyle
})
// render OpenStreetMap tile server
var tileLayer = new ol.layer.Tile({
source: new ol.source.OSM()
}, new ol.layer.Vector({
source: new ol.source.Vector({ features: [], projection: 'EPSG:4326' })
}))
// render cloud tile
let cloudLayer = new ol.layer.Tile({
source: new ol.source.XYZ({
url: api.mapTemperature()
})
})
let forecastLayer = new ol.layer.Tile({
source: new ol.source.XYZ({
url: api.forecast()
})
})
setTimeout(function () {
let layer = this.map.getLayers().getArray()[2]
layer.setSource(forecastLayer)
}.bind(this), 3000)
// create map
this.map = new ol.Map({
target: 'map',
layers: [
tileLayer,
markerLayer,
cloudLayer
],
view: new ol.View({
center: ol.proj.transform(geo, 'EPSG:4326', 'EPSG:3857'),
zoom: 4
})
})
}
layer.setSource should do the trick.
function onClick() {
layer.setSource(xyz2);
}
var xyz1 = new ol.source.XYZ({
url: 'https://server.arcgisonline.com/ArcGIS/rest/services/' +
'Demographics/USA_Percent_Over_64/MapServer/tile/{z}/{y}/{x}'
})
var xyz2 = new ol.source.XYZ({
url: 'https://server.arcgisonline.com/ArcGIS/rest/services/' +
'Demographics/USA_Percent_Under_18/MapServer/tile/{z}/{y}/{x}'
})
var layer = new ol.layer.Tile({
source: xyz1
});
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
layer
],
target: 'map',
view: new ol.View({
center: ol.proj.fromLonLat([0, 0]),
zoom: 3
})
});
Here is a working example:
layer.setSource Example

Specifying a minimum cluster size with Open Layers Clustering

With OpenLayers 3, how can I specify a minimum cluster size so that clusters with 5 map markers or less will not get clustered, but will instead display the individual map markers? Is there a way to do this within the cluster layer's ol.layer.Vector object?
let clusterSource = new ol.source.Cluster({
distance: CLUSTER_DISTANCE,
source: features
});
let clusterLayer = new ol.layer.Vector({
source: source,
style: function(feature, resolution) { }
});
You can check in the code how many features are there. If you have too many, you can create a cluster source based on the vector source you already have to add it a to a new vector layer. If not, a vector layer can be created with your existing vector source.
Since there is no method to set the source dynamically to a layer, your vector layer should be created with the desired source. If you want to see how it works with more than 5 features, just uncomment the commented lines.
var features = [
new ol.Feature({
geometry: new ol.geom.Point([0,0])
}),
new ol.Feature({
geometry: new ol.geom.Point([100000,500000])
}),
new ol.Feature({
geometry: new ol.geom.Point([500000,100000])
}),
new ol.Feature({
geometry: new ol.geom.Point([5000000,1000000])
}),
new ol.Feature({
geometry: new ol.geom.Point([1000000,500000])
})
/*,new ol.Feature({
geometry: new ol.geom.Point([1800000,800000])
})*/
],
source = new ol.source.Vector({
features: features
});
var layer;
if (features.length > 5) {
var clusterSource = new ol.source.Cluster({
distance: parseInt(40, 10),
source: source
});
var styleCache = {};
layer = new ol.layer.Vector({
source: clusterSource,
style: function(feature) {
var size = feature.get('features').length;
var style = styleCache[size];
if (!style) {
style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: '#AAA'
}),
fill: new ol.style.Fill({
color: '#DDD'
})
}),
text: new ol.style.Text({
text: size.toString(),
fill: new ol.style.Fill({
color: '#B144FF'
})
})
});
styleCache[size] = style;
}
return style;
}
});
} else {
layer = new ol.layer.Vector({
source: source
});
}
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
layer
],
target: 'clusterMap',
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
<link href="https://openlayers.org/en/v3.20.1/css/ol.css" rel="stylesheet"/>
<script src="https://openlayers.org/en/v3.20.1/build/ol.js"></script>
<div id="clusterMap" class="map"></div>

OpenLayers 3 - Z-index of features on highlights

I have some troubles with z-index on OpenLayers 3 when i want to highlight a feature.
I create a GeoJSON shape of a country, add some marker on top, and i want the shape color change when i hover on.
But, when the color change, the shape hide my markers.
I try to put zIndex style on the hightlight style but this doesn't change anything...
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})],
controls: ol.control.defaults({
attributionOptions: ({
collapsible: false
})
}),
target: 'map',
view: new ol.View({
center: [631965.84, 4918890.2],
zoom: 3
})
});
var vector = new ol.layer.Vector({
source: new ol.source.Vector({}),
style: new ol.style.Style({
zIndex: 1,
stroke: new ol.style.Stroke({
color: '#589CA9',
width: 3
}),
fill: new ol.style.Fill({
color: '#589CA9'
})
})
});
map.addLayer(vector);
var selectPointerMove = new ol.interaction.Select({
condition: ol.events.condition.pointerMove,
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#EF7F01',
width: 3
}),
zIndex: 1,
fill: new ol.style.Fill({
color: '#EF7F01'
})
})
});
map.addInteraction(selectPointerMove);
var feature = new ol.format.GeoJSON().readFeature(Some_GeoJSON_Coordinate, {
dataProjection: ol.proj.get('EPSG:4326'),
featureProjection: ol.proj.get('EPSG:3857')
});
vector.getSource().addFeature(feature);
iconFeature = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.transform([5, 44],"EPSG:4326", 'EPSG:3857')),
type:"marker"
});
var iconStyle = new ol.style.Style({
zIndex:2,
image: new ol.style.Icon(/** #type {olx.style.IconOptions} */ ({
anchor:[0.5,1],
scale:0.1,
src: 'https://lh4.ggpht.com/Tr5sntMif9qOPrKV_UVl7K8A_V3xQDgA7Sw_qweLUFlg76d_vGFA7q1xIKZ6IcmeGqg=w300'
}))
});
iconFeature.setStyle(iconStyle);
vector.getSource().addFeature(iconFeature)
I create a JSFiddle of my issue : http://jsfiddle.net/a1zb5kzf/1/
Thanks you in advance for your help
I found a solution.
According to the Select Interaction documentation, it's don't just apply an other Style but move your feature on a temporary overlay. And so, zIndex doesn't work because features aren't on the same layer anymore.
So, to get my highlight comportement and keep my feature on the same layer, i watch the pointermove event, and apply style if necessary. Just before, i memorized the feature, and reapply default style on it
cartoCtrl.map.on("pointermove", function (evt) {
var feature = cartoCtrl.map.forEachFeatureAtPixel(evt.pixel,
function (feature) {
return feature;
});
if (feature && feature.getProperties().type != "marker") {
cartoCtrl.lastHighlitedFeature = feature;
feature.setStyle(highlightStyle)
}));
} else {
if(cartoCtrl.lastHighlitedFeature){
cartoCtrl.lastHighlitedFeature.setStyle(defautlStyle);
cartoCtrl.lastHighlitedFeature = false;
}
}
});

Categories

Resources