0

I need to display many images (icons) on an OpenLayers map. I'm using v4.6.5

Previously, I was simply displaying 1 icon, and I was using PHP on the backend to determine a proper scale factor. This is no longer possible because I'm displaying up to 250 images, and it takes ~16 seconds to have PHP read the height of each image to adjust the scale factor for all of them, which is far too long of a load time for my webpage.

Users are inputting the images, so it's not possible for me to set them all as a fixed size. Here's a screenshot example of what I'm dealing with currently:

screenshot

Whereas what I need is for all of those flag images to be set at the same size. I have not been able to figure out through Google or the OL documentation how to set a fixed or absolute size for an image like this. Nor have I been able to find a workaround solution for this instance.

EDIT: Here is a sample excerpt from my code:

       new ol.layer.Vector({
            source: vectorSource = new ol.source.Vector({
                features: [
                    new ol.Feature({
                        geometry: new ol.geom.Point(ol.proj.fromLonLat([<?php echo $row['longitude']; ?>,<?php echo $row['latitude']; ?>])),
                        name: '<?php echo PWBASEURL . "nation/id=".$row['id']; ?>'
                    })
                ]
            }),
            style: new ol.style.Style({
                image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
                    anchor: [1, 1],
                    anchorXUnits: 'fraction',
                    anchorYUnits: 'fraction',
                    src: '<?php echo $row['flag']; ?>',
                    scale: 0.05
                }))
            })
        })
  • Welcome to GIS SE. As a new user, please be sure to take the tour to read up on our focused Q&A format. – Andy Oct 31 '18 at 2:16
  • You may prefer creating a thumbnail each time a user upload an image. Then when you serve your 250 images, they are already generated so no perf issue or asking OpenLayers to manage issues dues to your backend use case. – ThomasG77 Oct 31 '18 at 5:31
1

You could load the image as a property of the feature and use a style function to obtain its height or width to set an appropriate scale. This would set everything to 100px high

function loadImage(src) {
    var image = new Image();
    image.src= src;
    return image;
}



  new ol.layer.Vector({
        source: vectorSource = new ol.source.Vector({
            features: [
                new ol.Feature({
                    geometry: new ol.geom.Point(ol.proj.fromLonLat([<?php echo $row['longitude']; ?>,<?php echo $row['latitude']; ?>])),
                    name: '<?php echo PWBASEURL . "nation/id=".$row['id']; ?>'
                    image: loadImage('<?php echo $row['flag']; ?>')
                })
            ]
        }),
        style: function(feature) {
          var image = feature.getProperties().image;
          return new ol.style.Style({
            image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
                anchor: [1, 1],
                anchorXUnits: 'fraction',
                anchorYUnits: 'fraction',
                src: image.src,
                scale: 100 / image.height
            }))
          })
        }
    })
  • This seems super promising, but I can't quite get it to work. In Console I'm getting an error image is not defined and so I tried using feature.get('image').src and feature.get('image').height but that results in feature not defined. Any ideas? – Winch Oct 31 '18 at 18:47
  • I was able to figure it out. Thank you, your answer allowed my solution! – Winch Oct 31 '18 at 18:58
-1

Drawing off of @Mike's answer, I was able to work out a solution.

function loadImage(src) {
    var image = new Image();
    image.src = src;
    return image;
}

        new ol.layer.Vector({
            source: vectorSource = new ol.source.Vector({
                features: [
                    new ol.Feature({
                        geometry: new ol.geom.Point(ol.proj.fromLonLat([<?php echo $row['longitude']; ?>,<?php echo $row['latitude']; ?>])),
                        name: '<?php echo PWBASEURL . "nation/id=".$row['account_id']; ?>'
                    })
                ]
            }),
            style: new ol.style.Style({
                image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
                    anchor: [1, 1],
                    anchorXUnits: 'fraction',
                    anchorYUnits: 'fraction',
                    src: '<?php echo $row['flag']; ?>',
                    scale: 20 / loadImage('<?php echo $row['flag']; ?>').height
                }))
            })
        })

Here is the result, with uniformly sized images on my OpenLayers map: result

  • You should be cautious about using loadImage(src).height because image.src = src; sets off an asynchronous load of the url so height won't be available until the load has completed. It has probably worked in your case because setting src: src, in the line above caused the browser to cache it. For a more general solution I would still recommend using a style function so height is looked up when the feature is displayed, not when it is created. If you copied the code correctly I don't understand why feature would have been undefined, it's the parameter of the function. – Mike Nov 1 '18 at 12:49

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.