Displaying Static Images at 100% in OpenLayers - javascript

I would like to display static images as maps using a StaticImage layer in ol3, at 100% of the image size in pixels. I believe this should be defined by the extent and zoom variables, but the displayed images are not always the correct size, depending on the image, so I am clearly misunderstanding something, in spite of all of the forum entries I have read.
Here is a fiddle demonstrating incorrect image sizes. The reference image is 128x128 pix, but the displayed image is slightly larger at zoom 0.
The provided example from OpenLayers works just fine if used in my fiddle, and we seem to learn that if the extent variable is [0,0,wid,len], then zoom: 2 is 100%. But this does not hold with all images.
How can static images be reliably displayed at 100% of their size in pixels?
Thanks in advance for your help.
var extent = [0,0,128,128] // image size is 128x128 px
var projection = new ol.proj.Projection({
code: 'local_image',
units: 'pixels',
extent: extent
});
var map = new ol.Map({
target: 'map',
view: new ol.View({
projection: projection,
center: ol.extent.getCenter(extent),
zoom: 0,
}),
controls: [],
});
var im_layer = new ol.layer.Image({
source: new ol.source.ImageStatic({
url: 'http://img4.wikia.nocookie.net/__cb20071014061100/freeciv/images/1/1c/Crystal_128_penguin.png', // image size is 128x128 px
projection: projection,
imageExtent: extent
})
})
map.addLayer(im_layer)

I finally found an answer to this problem. Instead of using the "zoom" variable in the map view, use the "resolution" parameters instead.
Setting the following, in addition to the above, results in an image displayed at 100%:
var map = new ol.Map({
view: new ol.View({
resolution: 1, // important for 100% image size!
maxResolution: 2, // must be >= 1
//minResolution: .5, // also set-able
//zoom: 0, // don't use this
...
})
...
})
Here is an updated fiddle.

Related

Open Layers Features move when zooming out

EDIT: I changed the center of the map by user-input before but changed this for testing. Using a fixed center for my map, everything is fine. Question now is: why?
I am looping through a JSON with some features, extracting the coordinates for each feature, and add them to a map.
So far everything is working fine, but I just noticed that the features or better the icons are moving when I am zooming out/in or moe left/right.
The feature location should still be true since I am able to hover over the map and show an overlay (as intended).
I have no idea why the logos would behave like this, maybe someone can help me. Here is my code for one of the layers:
///////////////
// Forst
var Forststyle = new ol.style.Style({
image: new ol.style.Icon({
src: 'images/tree.png'
})
});
var Forstsource = new ol.source.Vector();
$.getJSON('config/Forst.json', function (data) {
$.each(data, function(key, val){
var newMarker = new ol.Feature({
geometry: new ol.geom.Point([this.long, this.lat]),
pointAttributes: {
'Name': this.name,
'Strasse':this.Straße,
}
});
Forstsource.addFeature(newMarker);
});
});
var Forst = new ol.layer.Vector({
title: "Forst",
visible: false,
zIndex: 5,
style: Forststyle,
source: Forstsource});
I am adding the Forst-Layer to the layers of my map.
I thought my projection/view definition might be helpful.
var projection25832 = new ol.proj.Projection({
code: 'EPSG:25832',
// The extent is used to determine zoom level 0. Recommended values for a
// projection's validity extent can be found at https://epsg.io/.
extent: [-1877994.66, 3932281.56, 836715.13, 9440581.95],
units: 'm'
});
I am adding my whole map-call. center and zoom get defined by user-input.
var map = new ol.Map({
target: 'map',
layers:[
new ol.layer.Tile({
title: 'OSM (grau)',
visible: true,
source: new ol.source.TileWMS({
url: 'https://ows.terrestris.de/osm/service?',
params: {
'LAYERS': "OSM-WMS",
'VERSION': '1.1.0',
'FORMAT': 'image/png',
'TILED': false
}
})
}),
Schaefer,
KMR,
GaLaBauSA,
GaLaBauBBG,
Forst,
Lohnunternehmen
],
view: new ol.View({
projection: projection25832,
center: center,
zoom: zoom
})
});
I am adding some images, view1 and view2 are only changed by scrolling left/right, view3 is zoomed in.
Some more edits:
As stated above, when I am using a fixed center everything is working as intended. However, changing it depending on User Input is not working.
var D = $.ajax({
type: "GET",
url: url,
dataType: "json"
}).done(function(){
var Coords = D.responseJSON.results[0].locations[0].latLng;
var utm = "+proj=utm +zone=32";
var new_center = [proj4("WGS84",utm,[Coords.lng, Coords.lat])[0],proj4("WGS84",utm,[Coords.lng, Coords.lat])[1]];
console.log(new_center);
CreateMap([new_center[0], new_center[1]],zoom);
$("#Hintergrund").hide();
});
}
My CreateMap function is taking the coordinates of the center and the zoom, the url is a WEB-API (mapquest) that turns input into coordinates. If I pass e.g. my home-zip-code I get the coordinates that are used as my fixed center in the log, so there should not be a problem with the coordinates right?
Your image moving on zoom, because it automatically scales so the size would be readable regarding the zoom level (It doesn't stick to the map) You would need to anchor the center of the image elsewhere.
To anchor the center image you must play around with offsets.
You can, play with offsets and image size itself with openlayers style class. I dont know which version you are using, so you most likely will have to read about it in the documentation or some other examples, but hare is one.
new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0, 0],
anchorXUnits: "pixels",
anchorYUnits: "pixels",
offset: [0,0],
offsetOrigin: 'bottom-left',
rotation: 0,
src: 'images/tree.png'
}))
});
Setting anchor to 0,0 will be top left if Im not mistaken, you most likely will have to set it to 0, {Half width}
Basically, when you scroll and zoom, OpenLayers adjusts your image scaling from its center point, so in theory it will move if the center point isnt for example at the bottom.
If that doesn't help, see if you have correct projections.
And if that doesn't help, try creating "Markers" instead of points, I don't recall but one of them has way more control flow going.
I imagined it moved by tiny bit, seems like it drastically moves. Might be projections fault. Try to use projection: 'EPSG:4326' if your coordinates are in different one, you can convert it with
.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"))
I noticed you create projection manualy, not sure if thats the best approach. Check out this one.
https://openlayers.org/en/latest/examples/epsg-4326.html
Its using 4326. It is always better to use openlayers projection and if you have coordinates built differently, transform them to your needed ones.
To debug this, you can try to draw a linestring on a map (WKT/Polyline) if that changes on zoom, your problem is definitely in projections, if not, then it might be something else.
I was working with openlayers recently as well. And ran into the same problem, which I made by add
style.graphicXOffset= 15;
style.graphicYOffset= 28;
Set these to 0, should help.

How to apply a custom local/offline map style to an OpenLayers Map

I have a local webpage as part of a larger desktop application. I want to change the default style of the Open Layer map to "Klokantech Basic". I've downloaded a copy of the style JSON but struggeerling to apply it to the map. Currently my code looks like:
var map = new ol.Map({
layers: [new ol.layer.Tile({ source: new ol.source.OSM() }), vectorLayer],
target: 'map',
style: './mapStyle.json',
view: new ol.View({
center: ol.proj.fromLonLat([-0.146953, 51.493758]),
zoom: 15
})
But setting a style isn't working, I've looked online and there appears to be Map Box, this however uses an API key, something which I don't want to use/ maintain.
The whole page and its resources are stored locally, is there any way of referencing the local style file without an API?
Here is my current code.
The mapbox style is for vector tile source and I pretend you use it for your vector layer.
Openlayers don't seem to support the Mapbox style for MVT. It use a style function to apply to the vector tile.You can see here a exemple of how Openlayers make style function for vector tiles.

Polygon drawing upon map tiles where a custom tile server is used using Openlayers 3

Has anyone tried drawing a polygon in an area where local server tiles are used in Openlayers3?
For a specific area on the map I am using local server tiles to visualize a building's plan while for the rest stamen tiles are used.
The issue is that once the polygon is drawn it "gets lost - disapears" under the tiles probably. If I try to draw a polygon on the area "outside" the one that custom tiles are rendered everything is ok.
I played a bit with the zIndex in the custom tiles but no luck. Any ideas?
I was trying to set the zIndex on both local tiles (to be lower than the drawn feature) and the drawn feature to be bigger than the local tiles but in the end as the drawn feature gets inserted into a Vector Layer I added a vector Layer on the map, set the zIndex there and once the polygon was drawn removed it using clear().
Thus,
Construct the vector Layer
var stamenTiles = new ol.layer.Tile({
source: new ol.source.Stamen({
layer: 'toner'
})
});
var source = new ol.source.Vector(); //DRAWING
var vector = new ol.layer.Vector({ //DRAWING
source: source,
zIndex: 100 // place the Polygon on top of the local tiles
});
Map object:
var map = new ol.Map({
target: 'map',
layers: [stamenTiles, vector],
view: new ol.View({
center: ol.proj.fromLonLat([CoordinatesFactory.getLongitude(), CoordinatesFactory.getLatitude()]),
zoom: 19,
minZoom: 19,
maxZoom: 22
})
});
Remove drawn vector layer
vector.getSource().clear();

OpenLayers 4, whenever you zoom with mousewheel fast the map dissapears

I have a map done with OpenLayers 4.3.2 with a lot of layers, sometimes 10, but only one shows at a time. The initialization of the map object is done like this:
var mousePositionControl = new ol.control.MousePosition({
coordinateFormat: ol.coordinate.createStringXY(4),
projection: 'EPSG:4326',
className: 'ol-lat-lon',
target: getElementById('location'),
undefinedHTML: ' '
});
//This is the control for the scale line at the bottom of t
var scaleLineControl = new ol.control.ScaleLine();
ol3view = new ol.View({
projection: _map_projection,
center: defCenter,
zoom: mapConfig.zoom,
maxZoom: mapConfig.zoomLevels,
zoomFactor: mapConfig.zoomFactor,
maxResolution: mapConfig.maxResolution
extent: resExtent // Not working
});
map = new ol.Map({
interactions: ol.interaction.defaults({mouseWheelZoom:false})
.extend([
new ol.interaction.MouseWheelZoom({
constrainResolution: true,
duration: 250, timeout: 200
})
]),
controls: ol.control.defaults()
.extend([mousePositionControl, scaleLineControl]),
overlays: [ol_popup], //Overlay used for popup
target: 'map', // Define 'div' that contains the map
renderer: 'canvas',
view: ol3view
});
What happens is that whenever i make a zoom with the mousewheel kinda fast the map disappears, it breaks.
The MouseWheelZoom interaction defined is an attempt to see if changing the times of the animation or Mouse wheel timeout of the zoom would stop breaking the map.
This bug occurs specially with Tiled layers that have streamlines but can be replicated with any layer.
I used to have this same web app done with OpenLayers 3 and this bug never ever happened, so it has definitely something to do with the new OpenLayers version, but I can't find a fix for it. Here is a link to the app I'm currently testing on, where you can replicate the bug: http://pronosticos.unam.mx:8080/MASTEROL4/mapviewer

How to add markers to OPENLAYERS map with JSON coordinates?

I am trying to zoom and add markers to a HTML openlayers map, so far I hardcoded the lat and long pulled from JSON result.
I would like in a first place to drop a marker at the location and then using lat and lng to create a function to avoid harcoding and being able to drop a marker for any JSON entry.
Here is my code so far, the location is well zoomed to the location but cant find how to drop a marker? Thanks!
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()})
],
view: new ol.View({
center: ol.proj.fromLonLat([103.835471, 1.303371]),
zoom: 6
}),
target: 'map'
});
Here are the basic steps you want to follow:
Create a vector layer (ol.layer.Vector) with a vector source (ol.source.Vector)
Include the layer in your map's "layers" array
Create a feature (ol.Feature) with the desired geometry
Call addFeature() on your vector source to add the feature to the layer
Make sure you transform the coordinates for your geometry if they are lat/lon.
The following may be helpful:
http://openlayers.org/en/v3.9.0/examples/icon.html

Categories