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,
});
Related
This is the code :
drawPoligon : function (vertices) {
debugger;
var map = peaMap;
var feature = new ol.Feature({
geometry: new ol.geom.Polygon([vertices])
});
var vectorSource= new ol.source.Vector({
features: [feature ]
});
var vectorLayer = new ol.layer.Vector({
source: vectorSource
});
map.addLayer(vectorLayer);
}
vertices = [1253906.08982072, 5430790.35506443, 1253935.16019819, 5430769.74133789, 1253951.90741865, 5430793.82802342, 1253955.42311216........]
Format of my coordinates array:
[
[1253906.08982072,5430790.35506443],
[1253935.16019819,5430769.74133789],
[1253951.90741865,5430793.82802342],
[1253955.42311216,5430798.88815272],
[1253953.91064413,5430800.28580152],
[1253952.03520923,5430801.40886153],
[1253945.88800332,5430791.50307534],
[1253936.62615957,5430797.3914173]
]
...The coordinates list isnt full. Only part of it for exposure.
The format [ [lon, lat], … ] is the correct one. With a bigger zoom you can see the result:
var osmLayer = new ol.layer.Tile({
source: new ol.source.OSM()
});
var vertices = [
[1253906.08982072, 5430790.35506443],
[1253935.16019819, 5430769.74133789],
[1253951.90741865, 5430793.82802342],
[1253955.42311216, 5430798.88815272],
[1253953.91064413, 5430800.28580152],
[1253952.03520923, 5430801.40886153],
[1253945.88800332, 5430791.50307534],
[1253936.62615957, 5430797.3914173]
];
var feature = new ol.Feature({
geometry: new ol.geom.Polygon([vertices])
});
var vectorSource = new ol.source.Vector({
features: [feature]
});
var vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: new ol.style.Style({
stroke: new ol.style.Stroke({
width: 2,
color: [255, 0, 0]
})
})
});
var map = new ol.Map({
layers: [osmLayer, vectorLayer],
target: document.getElementById("map"),
view: new ol.View({
center: [1253950, 5430800],
zoom: 20
})
});
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>
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
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
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>