Search code examples
javascriptangulartypescriptopenlayers

Openlayers set exact same scale as background-layer to all features


I used OpenLayers in Angular2 to show a custom SVG-image as a background map. This works perfectly and I can zoom and scroll across my map.

Now I implemented Features (also svg) and put them all in a seperate Vector-Layer above the map. They are all shown but when I zoom, they get resized weird.

When I zoom out, the Features are getting bigger, when I zoom in the features are getting smaller. I would like to have them always in the same size, so that they are getting smaller when I zoom out (as if it would be static content on the map).

I tried with an extra style-function and experimented by recalculation the scale of the current style of the feature. But I did not get this to work.

So my question ist: How do I put another Layer with Features above an existing layer and when zooming out everything gets smaller?

Am I doing something wrong? Do I need Projections? I am quite new to Openlayers.

Thanks in advance!

A minimal code example, the SVG-Points are getting bigger and bigger when zooming out (same problem at the OL code example: Official Code Example: When Zooming out, the marker gets as big as a whole country or continent....

let center = ol.proj.transform([8.30368, 47.05243], 'EPSG:4326', 'EPSG:3857');
let style = new ol.style.Style({
        image: new ol.style.Icon({
            anchor: [0, 0],
            anchorXUnits: 'pixels',
            anchorYUnits: 'pixels',
            src: '/assets/images/test.svg',
            imgSize: [50, 50],
            size: [50, 50],
            scale: 1.0
        })
    });

    let iconFeature = new ol.Feature({
        geometry: new ol.geom.Point(center)
    });

    iconFeature.setStyle((resolution) => {
        return [iconStyle];
    });

    this.featureArray.push(iconFeature);

    let vectorSource = new ol.source.Vector({
        features: this.featureArray
    });
    let extent = [0, 0, 1024, 968];
    let projection = new ol.proj.Projection({
        code: 'xkcd-image',
        units: 'pixels',
        extent: extent
    });

    // load vector layer for dynamic elements
    let vectorLayer = new ol.layer.Vector({
        source: vectorSource,
        projection: projection,
        imageExtent: extent
    });

    this.layerArray.push(vectorLayer);

    // basic setup
    this.map = new ol.Map({
        renderer: 'canvas',
        layers: this.layerArray,
        view: new ol.View({
            center: center,
            zoom: 16,
            minZoom: 1,
            maxZoom: 26,
        })
    });

Solution

  • You mean something like https://codepen.io/anon/pen/WOmqmN?&editors=1110?

    That requires a style function as style, where you scale the icon according to the resolution:

    function(feature, resolution) {
      style.getImage().setScale(16000 / resolution);
    }
    

    16000 ist the resolution at which the icon size should be the icon image's original size.

    Also note that the ol.layer.Vector instance is configured with

    updateWhileAnimating: true,
    updateWhileInteracting: true
    

    to make sure the icon size is updated whenever the resolution changes.