3

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! :)

  • 1
    You say you want the point to stay in the same place while you pan the map. Do you mean the same place geographically or relative to the screen/map window? If you wanted a car GPS like system you would set the marker latlng and the map centre latlng to the same value every 1 second. – BStone Jul 2 '13 at 9:06
  • Relative to the map window. And I am currently trying to do that - but I can only see a move() function that displaces the marker (geometry.point) and no function for me to set the value directly. Unless there is a way to directly alter attributes of the object...? – Jessica Yang Jul 2 '13 at 9:41
0

A quick and easy option would be to just remove the existing point and push a new point to the layer every second, which based on your code above, would look like this:

FOR every second
    ... update lon and lat with SSE ...
    LonLat = {new values}
    map.setCenter(center, zoom);
    var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(center),
         {some:'data'}, 
         {externalGraphic: 'img/marker.png', graphicHeight:25, graphicWidth:30}
    );
    markerLayer.removeAllFeatures();
    markerLayer.addFeatures(feature);
END FOR
  • The main iffy thing is that it feels weird to be constructing a new object every second without destroying the old ones. But a bit more tinkering that's pretty much what I have. Right now there's an oddity where sometimes the feature moves a tiny bit without the map moving (I am guessing since the map is still more-or-less 'centered' on the new coordinates of the feature), and then the next second the map moves to center on the new coordinates while the feature stays in the center. – Jessica Yang Jul 3 '13 at 7:45
  • Good point, you could destroy the layer and recreate. Not sure about the map and point not always updating. Perhaps the basemap layer has some sort of tolerance to prevent the map from reloading if it is essentially the same spot. – BStone Jul 3 '13 at 12:29
  • I'm pretty sure that's what's happening with the basemap. I profiled things for a bit and I don't think creating a new object each second is really doing much harm, so sticking with that for now. Thanks! – Jessica Yang Jul 4 '13 at 8:49
1

Here is what I'm currently using to display an icon of a plane that stays fixed while the map moves. It seems to work well.

Global variables at the top of my script: lat, lon, heading.

In the StyleMap for the iconLayer, specify rotation:'${angle}' in options. This will get the attribute angle (which I am using to store the heading of the plane) from features on that layer later.

In my updating script: every second, assign lat, lon, heading new values from the server; and then call map.setCenter([lon, lat]) and also this:

iconLayer.removeAllFeatures();
iconFeature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lon, lat), {angle: heading});
iconLayer.addFeatures(iconFeature);
1

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>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.