Openlayers3 markers are not showing up on os map - javascript

While ago I had help over so about setting up a project where I need to mark random building in NYC and display some info about the building, long story short, I have displayed a openstreetmap using openlayers3, view is fix to Astoria(Queens, NYC).
Now popup is working but markers are not displaying.
I have tried to experiment and change geometry from this
geometry: new ol.geom.Point(ol.proj.fromLonLat([-73.927870, 40.763633]))
to this ol.geom.Point(ol.proj.transform([-73.920935,40.780229], 'EPSG:4326', 'EPSG:3857')),
and use transform instead fromLonLat, but that didn't displayed them, next thing was src in styleIcon, I have download the standard openlayers3 marker and tried to add it from the image folder like src: 'img/icon.png', but that didn't work to.
Can someone please help me understand what is going on, why are mine markers not displaying properly on the map?
This is the JSFiddle for this project, you will see the popup working but no markers.
This JSFiddle is updated and it is working now, markers are displaying properly.
/* Create the map */
// Elements that make up the popup
var container = document.getElementById('popup');
var content = document.getElementById('popup-content');
var closer = document.getElementById('popup-closer');
// Add a click handler to hide the popup.
// #return {boolean}.
closer.onclick = function() {
overlay.setPosition(undefined);
closer.blur();
return false;
};
// Create an overlay to anchor the popup
// to the map
var overlay = new ol.Overlay({
element: container,
autoPan: true,
autoPanAnimation: {
duration: 250
}
});
// setting up coordinates for map to display
var city = ol.proj.transform([-73.920935,40.780229], 'EPSG:4326', 'EPSG:3857');
// setting up openlayer3 view
var view = new ol.View({
center: city,
zoom: 15
});
// Create the map
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM({
crossOrigin: 'anonymous'
})
})
],
overlays: [overlay],
target: 'map',
view: view
});
// Setup markers
var markers = new ol.layer.Vector({
source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([-73.927870, 40.763633])),
name: 'Crescent St',
description: 'Apartment'
}),
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([-73.917356, 40.763958])),
name: 'Long Island City',
desctiption: 'Apartment'
})
]
}),
style: new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixel',
opacity: 0.75,
src: 'https://openlayers.org/en/v3.12.1/examples/data/icon.png',
})
})
});
map.addLayer(markers);
// Setting up click handler for the map
// to render the popup
map.on('singleclick', function(evt) {
var name = map.forEachFeatureAtPixel(evt.pixel, function(feature) {
return feature.get('name');
})
var coordinate = evt.coordinate;
content.innerHTML = name;
overlay.setPosition(coordinate);
});
map.on('pointermove', function(evt) {
map.getTargetElement().style.cursor = map.hasFeatureAtPixel(evt.pixel) ? 'pointer' : '';
});

just remove the https from your src style.
Instead of src: 'https://openlayers.org/en/v3.12.1/examples/data/icon.png',
putsrc: 'http://openlayers.org/en/v3.12.1/examples/data/icon.png',
You also need to zoom out a bit to see your marks

Related

Openlayers Hover render order, hover feature rendering over all other features

I'm looking for a way to render a hover feature vector only over that feature, to essentially render the hover vector over its feature without rendering over other features (specifically, LineString hovers not rendering over proximate markers)
I have hovering set up without issue as per the vector example, the features all rendering in the order I would like (LineStrings are below markers). The issue is that when a LineString is hovered over its hover feature is rendered not only over that LineString but also any marker that the LineString crosses under, and so there is a big streak of the LineString's hover over that marker. I can see how this makes sense just considering how the feature-overlaying vector works, but I can't see how to adjust it as I would like.
I've found several posts that seem to offer incongruous advice on setting a zIndex in the styles or using a renderOrder function, though none have seemed exactly applicable to this situation, or are beyond my n00b capacities. I have tried setting a zIndex on all concerned Styles as well as something along the lines of this renderOrder function, but not to the desired effect. Specifically with the latter, I couldn't figure out where to put the function so that the hover might render according to it.
Any advice is greatly appreciated!
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: 'map',
view: new ol.View({
center: ol.proj.fromLonLat([132.4903, 34.0024]),
zoom: 4
})
});
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
url: '../static/gpx/summer3.kml',
format: new ol.format.KML({
extractStyles: false
})
}),
style: function(feature) {
return routeStyle;
},
});
vectorLayer.getSource().on('addfeature', function(event) {
event.feature.set('hoverstyle', 'route');
});
map.addLayer(vectorLayer);
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
url: '../static/gpx/testmoo3.kml',
format: new ol.format.KML({
extractStyles: false,
}),
}),
style: function(feature) {
return iconStyle;
},
});
vectorLayer.getSource().on('addfeature', function(event) {
event.feature.set('hoverstyle', 'route');
});
map.addLayer(vectorLayer);
var hoverStyles = {
'moo': new ol.style.Icon({
anchor: [0.5, 30],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: '../static/GPX/icon/mooinb.png',
}),
'route': new ol.style.Stroke({
color: 'rgba(236, 26, 201, 0.5)',
width: 5
})
};
var routeStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'rgba(209,14,14,.6)',
width: 4
})
});
var iconStyle = new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 30],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: '../static/GPX/icon/moo7.png',
}),
});
var hoverStyleCache = {}
function hoverStyler(feature, resolution) {
var hover = feature.get('hoverstyle');
var geometry = feature.getGeometry().getType();
console.log(hover);
while (geometry === 'Point') {
if (!hoverStyleCache[hover]) {
hoverStyleCache[hover] = new ol.style.Style({
image: hoverStyles[hover],
})
}
return [hoverStyleCache[hover]];
}
while (geometry === 'LineString') {
if (!hoverStyleCache[hover]) {
hoverStyleCache[hover] = new ol.style.Style({
stroke: hoverStyles[hover]
})
}
return [hoverStyleCache[hover]];
}
}
var featureOverlay = new ol.layer.Vector({
source: new ol.source.Vector(),
map: map,
style: hoverStyler
});
var highlight;
var hover = function(pixel) {
var feature = map.forEachFeatureAtPixel(pixel, function(feature) {
return feature;
});
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;
}
var pixel = map.getEventPixel(evt.originalEvent);
hover(pixel);
});
***** EDIT 1 *****
Here is a plunkr that at least illustrates what I mean (with the hover vector overlapping the marker).
I continued fiddling around and did get manage to achieve what I wanted, by separating the point and linestring 'featureOverlay' vector into two separate vectors, though to get that to work I also then had to duplicate everything that it implies (the hoverStyler function, the hover feature, etc).
As well, when I referred above to incongruous advice that came especially to the fore as I was able to set the zIndex on that any vector layer, but not in the Styles as I read in just about every other question I found but to the vector itself. Thus,
var featureOverlay = new ol.layer.Vector({
source: new ol.source.Vector(),
map: map,
style: hoverStyler,
zIndex: 1,
});
worked (with zIndex similarly applied to ever other vector layer), but because points and linestrings share the feature Overlay that also meant that the marker's hover vector image was below the marker it was meant to hover over: applied in this way both linestring and markers or neither hover above.
I thus tried to come up with a function similar to the hoverStyler that differentiates them:
function zIndexer(feature, resolution) {
var geometry = feature.getGeometry().getType();
if (geometry === 'Point') {
return 5
}
if (geometry === 'LineString') {
return 1
}
}
but to no avail (I was unsure what exactly should be returned and tried various inputs; this as others did not work).
So I could settle for duplicated featureOverlay apparatuses, but a handy zIndex function would be of course be preferable :)
(*note: I could not get the zIndex to work in the plunkr as described above, in or out of Styles, hence it does not illustrate my later fiddling but only the original question)
***** EDIT 2 *****
I noted in a comment below on the provided answer that, while the answer works wonderfully, it did make cluster styles styled by function (not mentioned in the original post0 not work. I overcame this with the following vector, which worked but that I am not qualified to say worked well:
var clusterCache = {}
var CLM = new ol.layer.Vector({
source: new ol.source.Vector(),
style: function(feature) {
var size = feature.get('features').length;
var style = clusterCache[size]
if (size === 1) {
return [hoverStyles['moo']]
}
else if (size > 1) {
if (!style) {
style = new ol.style.Style({
image:new ol.style.Icon({
anchor: [0.5, 30],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: '../static/GPX/icon/moo3Hover.png',
}),
text: new ol.style.Text({
text: size.toString(),
font: '12px Calibri,sans-serif',
fill: new ol.style.Fill({
color: '#fff'
}),
stroke: new ol.style.Stroke({
color: '#000',
width: 5
}),
offsetX: 22,
offsetY: 6,
})
}),
clusterCache[size] = style;
}
return style;
}
}
});
hoverLayers['clustermoo'] = CLM;
Approach
The basic idea is you need separate hover layers for the route and the icons (top to bottom):
Icon hover layer
Icon layer
Route hover layer
Route layer
This will mean that say an unhovered icon will draw over the top of a hovered route.
ZIndex
You can't use the style zIndex as it applies only to features within a layer. That is, the layer zIndex has a higher precedence than the style zIndex. In your plunkr I couldn't get the layer zIndex to work at all, but it is implicit in the order the layers are added.
So, you need to:
create separate hover layers
setup the layers in the order I gave above
when hovering a feature, move it to the appropriate hover layer
when unhovering a feature, remove it from the appropriate hover layer
Style Cache
Another thing, your style cache implementation was rather dubious. In fact you do not need a style cache as your are using layer styles and they are only assigned/created once.
Plunkr
Here is an updated plunkr with the above changes: https://plnkr.co/edit/gpswRq3tjTTy9O0L
var createHoverLayer = function(style) {
return new ol.layer.Vector({
source: new ol.source.Vector(),
style: style,
});
}
var hoverLayers = {};
hoverLayers['route'] = createHoverLayer([hoverStyles['route']]);
hoverLayers['moo'] = createHoverLayer([hoverStyles['moo']]);
map.addLayer(routeLayer);
map.addLayer(hoverLayers['route']);
map.addLayer(mooLayer);
map.addLayer(hoverLayers['moo']);
var highlight;
var hover = function(pixel) {
var feature = map.forEachFeatureAtPixel(pixel, function(feature) {
return feature;
});
if (feature !== highlight) {
if (highlight) {
var highlightType = highlight.get('type');
hoverLayers[highlightType].getSource().removeFeature(highlight);
}
if (feature) {
var featureType = feature.get('type');
hoverLayers[featureType].getSource().addFeature(feature);
}
highlight = feature;
}
};
Alternative Approach
do not use separate hover layers at all
use per feature styling via style function
when the feature is hovered/unhovered, set a 'hovered' property on it
to true/false
in the style function, check this property and use the appropriate
style
you will need a style cache with this method

Image is displayed wrong on static image layer on top of osf layer

I followed the example from the openlayers book to add a static image on top of an osf layer. It works, but my image (256x256) is displayed as a rectangle. I tried around with the coordinates for the projection and checked out other posts here on, but I can't get my head around it why the image is not displayed as a square:
// Create map
var map = new ol.Map({
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()
})
],
// Create a view centered on the specified location and zoom level
view: new ol.View({
center: ol.proj.transform([16.3725, 48.208889], 'EPSG:4326', 'EPSG:3857'),
zoom: 4
})
});
// Create an image layer
var imageLayer = new ol.layer.Image({
opacity: 0.75,
source: new ol.source.ImageStatic({
attributions: [
new ol.Attribution({
html: ''
})
],
url: 'https://placebear.com/256/256',
imageSize: [256, 256],
projection: map.getView().getProjection(),
imageExtent: ol.extent.applyTransform(
[0, 0, 16.3725, 48.208889], ol.proj.getTransform("EPSG:4326", "EPSG:3857"))
})
});
map.addLayer(imageLayer);
ol.source.ImageStatic was made to put a georeferenced image (e.g. a scan of a historic map) on a map. Is this what you have in mind? If you just want to display an image and anchor it to a location on the map, you'd better use ol.Overlay or an ol.layer.Vector with a feature with an ol.style.Icon.
That said, your image will only be displayed as square if the imageExtent set on your ol.source.ImageStatic results in a square on the projected map view.

Click a line and open popup OpenLayers 3

I'm loading a GPX file into my OL3 code. Now i'd like to whole line that the GPX makes to be clickable with some extra information. Now I can't for the life of me find a way to click the line drawn for the route. What listener can I use?
I don't want to click on the whole map but just the line.
I've tried attaching click/singleclick to vector to no avail.
Any ideas on how to do so?
My code:
var raster = new ol.layer.Tile({
source: new ol.source.OSM()
});
var style = {
'LineString': new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#000',
width: 3
})
}),
'MultiLineString': new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#000',
width: 3
})
})
};
var vector = new ol.layer.Vector({
source: new ol.source.Vector({
url: 'kust.gpx',
format: new ol.format.GPX()
}),
style: function(feature) {
return style[feature.getGeometry().getType()];
}
});
var map = new ol.Map({
layers: [raster, vector],
target: document.getElementById('map'),
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
Try adding the click on the map, and in the handler you check on wich feature you clicked. For example:
map.on('click', displayFeatureInfo);
function displayFeatureInfo( evt ){
//get pixel position of click event
var pixel = evt.pixel;
var features = [];
//loop through all features under this pixel coordinate
//and save them in array
map.forEachFeatureAtPixel(pixel, function(feature, layer) {
features.push(feature)
});
//the top most feature
var target = features[0];
//...rest of code
target.get('customProp')
}
EDIT
You can put some extra juice in your feature by inserting extra properies to the passed object. for example:
var myFeature = new ol.Feature({
geometry: ...,
labelPoint: ..,
name:...,
customProp1: ...,
anothercustomProp: ...
})

Plot icon on map, based on user's input in Openlayers 3

We upgrading our app with the recent Openlayers 3 maps. And it seems OL 3 use completely different approach in comparisons what they've used in OL 2. Not very good in JS.
We want that user be able to input coordinates (lon, lat) into text fields, press the button and the icon appear on the map. And vice versa - when user click (single click) on the map, these coordinates (lon, lat) should popup on these text fields, to be able save and update it into the DB in the future.
So far I was able to display the map, icon appear on user's click, and completely stuck on how to get coordinates and display them into the text fields. And can't figure out how to make user type in coordinates and get the icon on that location. Here is my code so far:
html
<div id="map" tabindex="0"></div>
<div id="txt">Click to add a marker!</div>
<form>Lon:<input type="text" id="lon" name="lon">
<br>Lat:<input type="text" id="lat" name="lat">
<input type="button" id="get" onlclick = "getLocation" value="plot icon"></form>
And here is JS:
var vectorSource = new ol.source.Vector(),
vectorLayer = new ol.layer.Vector({
source: vectorSource
}),
olview = new ol.View({
center: [0, 0],
zoom: 4,
minZoom: 2,
maxZoom: 20
}),
map = new ol.Map({
target: document.getElementById('map'),
view: olview,
layers: [
new ol.layer.Tile({
style: 'Aerial',
source: new ol.source.MapQuest({ layer: 'osm' })
}),
vectorLayer
]
});
var iconStyle = new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
opacity: 0.75,
src: '//openlayers.org/en/v3.8.2/examples/data/icon.png'
}),
text: new ol.style.Text({
font: '12px Calibri,sans-serif',
fill: new ol.style.Fill({ color: '#000' }),
stroke: new ol.style.Stroke({
color: '#fff', width: 2
}),
text: 'lon and lat'
})
});
map.on('click', function(evt){
var feature = new ol.Feature(
new ol.geom.Point(evt.coordinate)
);
feature.setStyle(iconStyle);
vectorSource.clear();
vectorSource.addFeature(feature);
getLocation();
});
function getLocation() {
alert('how to get lon and lat ?!?'); }
You can get the coordinates from a click by calling
evt.coordinate
or
map.getEventCoordinate(evt.originalEvent);
So in your case it would look like:
map.on('click', function(evt) {
var coordinate1 = evt.coordinate;
var coordinate2 = map.getEventCoordinate(evt.originalEvent);
getLocation(coordinate1);
getLocation(coordinate2);
});
function getLocation(coordinate) {
alert(coordinate);
}
To add a marker to a certain point you can follow this example:
how to add markers with OpenLayers 3
(jsfiddle)
Where
ol.geom.Point(ol.proj.transform([Math.random()*360-180, Math.random()*180-90], 'EPSG:4326', 'EPSG:3857')),
would be your desired coordinates e.g.
ol.geom.Point(ol.proj.transform([0.5, 46], 'EPSG:4326', 'EPSG:3857')),
map.on('click', function (evt) {
var lonlat = ol.proj.transform(evt.coordinate, 'EPSG:4326', 'EPSG:3857');
var lon = lonlat[0];
var lat = lonlat[1];}
for getting long and lat you can change EPSG according to your need

How to easily create a heatmap layer from a pre-existing vector layer of points in OpenLayers 3?

Like the title said I have a vector of points on a OpenLayers map that I need to turn into a heatmap. I already have this code below (which works just fine for me) but I need to add thousands of more points(in a different data file) and be able to visualize it with a density/heatmap. Its current state is a simple open street map with one layer of locations plotted on a world map! I would post an image but reputation rules...
<!DOCTYPE HTML>
<html>
<head>
<title>AIS Map Template</title>
<script src="http://www.openlayers.org/api/OpenLayers.js"></script>
<script>
function init() {
map = new OpenLayers.Map("mapdiv");
var mapnik = new OpenLayers.Layer.OSM();
map.addLayer(mapnik);
// ADD POINTS TO A LAYER
var pois = new OpenLayers.Layer.Vector("Ships",
{
projection: new OpenLayers.Projection("EPSG:4326"),
strategies: [new OpenLayers.Strategy.Fixed()],
protocol: new OpenLayers.Protocol.HTTP(
{
url: "./AISdecoded.txt",
format: new OpenLayers.Format.Text(
{
extractStyles: true,
extractAttributes: true
})
})
});
// ADD POINTS LAYER TO MAP
map.addLayer(pois);
var layer_switcher= new OpenLayers.Control.LayerSwitcher({});
map.addControl(layer_switcher);
var lonlat = new OpenLayers.LonLat(0,0).transform(
new OpenLayers.Projection("EPSG:4326"), // transform from WGS 1984
new OpenLayers.Projection("EPSG:900913") // to Spherical Mercator
);
var zoom = 1;
map.setCenter(lonlat, zoom);
}
</script>
<style>
#mapdiv { width:900px; height:600px; }
div.olControlAttribution { bottom:3px; }
</style>
</head>
<body onload="init();">
<p>AIS Map Data</p>
<div id="mapdiv"></div>
</body>
</html>
The testing data looks like this:
lat lon title description icon iconSize iconOffset
49.4756 0.13138 227006760 Navigation Status: 0 ship_sea_ocean.png 16,16 -8,-8
51.2377 4.41944 205448890 Navigation Status: 0 ship_sea_ocean.png 16,16 -8,-8
I have tried various methods to try and get a heatmap produced but unfortunaetly I'm a little lacking on the Javascript/HTML side of things. I have looked at the examples online including the earthquake example provided by OpenLayers but 99% of them deal with KML files and since I need this application to run offline on a localhost server I cannot do it that way.
I have attempted this without success, among other flailing:
var heatmapLayer = new ol.layer.Heatmap({
source: new OpenLayers.Layer.Vector("Ships",
{
projection: new OpenLayers.Projection("EPSG:4326"),
strategies: [new OpenLayers.Strategy.Fixed()],
protocol: new OpenLayers.Protocol.HTTP(
{
url: "./AISdecoded.txt",
format: new OpenLayers.Format.Text(
{
extractStyles: true,
extractAttributes: true
})
})
}),
opacity: 0.9
});
// Create a tile layer from OSM
var osmLayer = new ol.layer.Tile({
source: new ol.source.OSM()
});
// Create the map with the previous layers
var map = new ol.Map({
target: 'map', // The DOM element that will contains the map
renderer: 'canvas', // Force the renderer to be used
layers: [osmLayer, heatmapLayer],
// Create a view centered on the specified location and zoom level
view: new ol.View({
center: ol.proj.transform([2.1833, 41.3833], 'EPSG:4326', 'EPSG:3857'),
zoom: 4
})
});
I have a feeling this is much easier than I think it is but I have been trying to do this for about a week now and my patience is nearing its end. If you know how to do this specifically that's awesome! But if you don't, can you push me in the right direction? Any help is much appreciated, thanks!
EDIT
OK so I edited the code a bit to be fully OL3 and use a geoJSON approach. It now looks like this:
<!DOCTYPE HTML>
<html>
<head>
<title>AIS Map Template</title>
<script src="http://openlayers.org/en/v3.5.0/build/ol.js" type="text/javascript"></script>
<link rel='stylesheet' href='http://ol3js.org/en/master/css/ol.css'>
<script>
function init() {
var vector = new ol.layer.Heatmap({
source: new ol.source.GeoJSON({
url: './AISdecoded.geojson',
projection: 'EPSG:3857'
}),
opacity: .9
});
var osmLayer = new ol.layer.Tile({
source: new ol.source.OSM()
});
// Create the map with the previous layers
var map = new ol.Map({
target: 'map', // The DOM element that will contain the map
renderer: 'canvas', // Force the renderer to be used
layers: [osmLayer,vector],
// Create a view centered on the specified location and zoom level
view: new ol.View({
center: ol.proj.transform([2.1833, 41.3833], 'EPSG:4326', 'EPSG:3857'),
zoom: 4
})
});
}
</script>
<style>
#map { width:900px; height:600px; }
div.olControlAttribution { bottom:3px; }
</style>
</head>
<body onload="init();">
<p>AIS Map Data</p>
<div id="map"></div>
</body>
</html>
But it's still not working, only a map, no layer. This is the way I found how to do via examples like this one. Firebug is saying "TypeError: ol.source.GeoJSON is not a constructor" but I don't know how to do this any other way. pls halp, thanks!
Change this:
var vector = new ol.layer.Heatmap({
source: new ol.source.GeoJSON({
url: './AISdecoded.geojson',
projection: 'EPSG:3857'
}),
to:
var vector = new ol.layer.Heatmap({
source: new ol.source.Vector({
url: './AISdecoded.geojson',
projection: 'EPSG:3857',
format: new ol.format.GeoJSON()
}),

Categories

Resources