[GIS] OpenLayers: How to keep a feature fixed while the map layer is moved (like in-car GPS displays)

markersopenlayers-2

I am aiming to create something simple that works like a GPS navigation display, where the marker for 'you are here' is fixed while the map moves along. I have latitude and longitude coordinates supplied but when I move the map, the marker moves too – even though I tried setting the marker's layer to isFixed: true.

Here's what I'm using to set up the map:

var map = new OpenLayers.Map('map');
var baseLayer = new OpenLayers.Layer.MapServer('base layer', 'url', {map: 'something.map'}, {layers: 'base'}, {transitionEffect: 'resize'}, {gutter:'15'});

var markerLayer = new OpenLayers.Layer.Vector('marker', {isFixed : true});
var feature = new OpenLayers.Feature.Vector(
  new OpenLayers.Geometry.Point(100, 1.5),
  {some:'data'}, {externalGraphic: 'img/marker.png', graphicHeight:25, graphicWidth:30});
markerLayer.addFeatures(feature);

map.addLayer(baseLayer);
mapp.addLayer(markerLayer);
map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);

A script at the bottom of my HTML updates lat and lon with coordinates (in degrees) pushed to it every second via a server-side event. After that, every second I am calling map.setCenter(new OpenLayers.LonLat(lon, lat), zoom) to re-center the map.

At first I thought that if I drew my feature on a new, fixed layer, it wouldn't move, but the feature seems to be being drawn at 100N 1.5E, and staying there despite me panning the map. I want the marker to just stay where it is no matter how you pan the map.

P.S. My map re-centering feels rather inefficient as I am creating a new LonLat every time, but I couldn't figure out from the API docs any way to directly update it e.g.:

center = new OpenLayers.LonLat(lon, lat);
map.setCenter(center, zoom);
FOR every second
  ... update lon and lat with SSE ...
  center = new OpenLayers.LonLat(lon, lat);
  map.setCenter(center, zoom);
END FOR

Any help or suggestions would be much appreciated! 🙂

Best Answer

If anyone is still looking for an answer for OpenLayers 2.x how to display a fixed graphic, which always stays in the map center - you might want to look into the following workaround. There is no need to periodically execute code to move the image, when the underlying map is being moved.

Full and working HTML5 example:

JSFiddle: https://jsfiddle.net/xvz86tf7/


<!DOCTYPE html>
<html>
<head>
<title>fixed panel in map center</title>
<meta charset="utf-8" />
<script type="text/javascript" src="https://openlayers.org/api/OpenLayers.js"></script>
<script type="text/javascript">
function init()
    {
    projmerc = new OpenLayers.Projection("EPSG:900913");
    proj4326 = new OpenLayers.Projection("EPSG:4326");
    map = new OpenLayers.Map("mapdiv",
        {
        projection: projmerc,
        displayProjection: proj4326,
        controls:
            [
            new OpenLayers.Control.MousePosition(),
            new OpenLayers.Control.KeyboardDefaults(),
            new OpenLayers.Control.Navigation(),
            ],
        }
    );
    var maplayer = new OpenLayers.Layer.OSM("OpenStreetMap");
    map.addLayer(maplayer);
    var mapcenter = new OpenLayers.LonLat(-73.97, 40.78);
    map.setCenter(mapcenter.transform(proj4326, projmerc), 14);
    var mappanel = new OpenLayers.Control.Panel();
    map.addControl(mappanel);
    }
window.onload = init;
</script>
<style type="text/css">
#mapdiv
    {
    width: 500px;
    height: 400px;
    }
.olControlPanel
    {
    display: block;
    left: 50%;
    top: 50%;
    width: 50px;
    height: 90px;
    /* CAUTION: you will have to adjust the negative margins left and top to background image width and height */
    margin: -45px 0px 0px -25px;
    background-image: url("data:image/png;base64,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");
    }
</style>
</head>
<body>
<div id="mapdiv"></div>
<button onclick="alert(map.getCenter().transform(projmerc, proj4326).toString())">Show car position (map center)</button>
</body>
</html>