简体   繁体   中英

OpenLayers 3: Trying to add image underlay to a vector layer

currently i have a vector map displayed using a KML file as the vector source.

what i want to do is have an image underlay this vector map.

The map is an indoor floormap, the image is the exact same as the vector map only there is more details in it, text written on it etc. What i need is for the map image to underlay the vector map so that the walls of the vector map align perfectly with the walls of the image. This can happen because the KML was created by tracing on top of the images using QGIS.

so far ive been able to have the KML vector map and png image appear on the map, but they are not alligned with each other and are not the same size. This is what i need help with!

here some code for what i currently have:

create the map, no layers yet (maps selected from dropdown boxes)

var map = new ol.Map({
  layers: [],  
  target: 'floormap',
  interactions: ol.interaction.defaults({mouseWheelZoom:false}),
  view: new ol.View({
      center: [0, 0],          
      zoom: 19,
      minZoom: 15,
      maxZoom: 30
    })    
});   

add selected map (KML) to map

map.removeLayer(vector);

vector = new ol.layer.Vector({
    source: new ol.source.Vector({
        url: MAPS_URL + maps[map_id],
        format: new ol.format.KML()
    })
});        

map.addLayer(vector);
setMapExtent(vector);  

now i tried to add the image, which works but its not alligned

// this part here i feel may be the problem, 
// i just copied and pasted from an example om openlayers.org, 
// i dont actually know much about the extent and how to match it to 
// the vector map
var extent = [0,0,1024,684];

var projection = new ol.proj.Projection({
    code: 'xkcd-image',
    units: 'pixels',
    extent: extent
});

image = new ol.layer.Image({
    source: new ol.source.ImageStatic({
        attributions: [
            new ol.Attribution({
                html: '&copy; <a href="http://xkcd.com/license.html">xkcd</a>'
            })
        ],
        url: MAPS_URL + images[map_id],
        projection: projection,
        imageExtent: extent
    })
});

map.addLayer(image);

the setMapExtent method

function setMapExtent(vectorMap) {
    var vectorSource = vectorMap.getSource();
    var listenerKey = vectorSource.on('change', function () {
        if (vectorSource.getState() === 'ready') {
            var extent = vectorSource.getExtent();
            map.getView().fitExtent(extent, map.getSize());
            vectorSource.unByKey(listenerKey);
        }
    });
}  

at this point i have a vector map with an image sitting way above the map, and the image seems to be smaller too.

Can anyone help me with this issue?

*** Solution! ***

a working solution, although probably not the best way to do it, but it works none the less.

var map = new ol.Map({
   layers: [],  
   target: 'floormap',
   interactions: ol.interaction.defaults({mouseWheelZoom:false}),
   view: new ol.View({
   center: [0, 0],          
   zoom: 19,
   minZoom: 15,
   maxZoom: 30
 })    

});

add new map layer

map.removeLayer(vector);

vector = new ol.layer.Vector({
    source: new ol.source.Vector({
        url: MAPS_URL + maps[map_id],
        format: new ol.format.KML()
    })
});        

map.addLayer(vector);
setMapExtent(vector);   

// call image adding function pass in vector
// to get its extend
addImage(vector);

the addImage function

function addImage(vectorMap) {

    var vectorSource = vectorMap.getSource();

    // listen for one change on the vector to get the extent of it
    // for use in setting the image extent. tried to use on.('load')
    // but it didnt work
    var listenerKey = vectorSource.once('change', function () {

        var extent = vectorSource.getExtent();

        var projection = new ol.proj.Projection({
            code: 'xkcd-image',
            units: 'pixels',
            extent: extent
        });

        image = new ol.layer.Image({
            source: new ol.source.ImageStatic({
                attributions: [],
                url: MAPS_URL + images[map_id],
                projection: projection,
                imageExtent: extent
            })
        });

        // remove vector layer else they keep stacking up
        map.removeLayer(vector);
        // add image
        map.addLayer(image); 
        // re-add vector only push so it goes above the image
        map.getLayers().push(vector); 

    });
}

seems to work pretty well! can anyone help me with layer ordering?

Your static image must be georeferenced correctly with the view's projection.

Default view's projection is EPSG:3857 (Spherical Mercator). , the extent of this projection is [-20026376.39, -20048966.10, 20026376.39, 20048966.10]

In your code you specify a projection in pixels for your static layer. You need to use the view's projection, something like this :

    // Here the extent of your layer in EPSG:3857  -> [minx, miy, max, mayy]
    var extent = [-10000000, -10000000, 10000000, 10000000];

    image = new ol.layer.Image({
        source: new ol.source.ImageStatic({
            attributions: [
                new ol.Attribution({
                    html: '&copy; <a href="http://xkcd.com/license.html">xkcd</a>'
                })
            ],
            url: MAPS_URL + images[map_id],
            imageSize: [1024, 684],  // Don't forget the image size here
            imageExtent: extent
        })
    });

    map.addLayer(image);

Update:

For layer ordering if you want your vector layer on top use push:

http://openlayers.org/en/v3.8.2/apidoc/ol.Collection.html#push

map.getLayers().push(vector)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM