whatdym
whatdym

Reputation: 17

In openlayers, how to fit (stretch) a picture from a url in the polygon?

I try to add a picture in a polygon I found this answer In openlayers 3, how to fill the polygon with a picture from a url?

However, I would like to fit (stretch) picture in the polygon (cause I aim to add feature that can resize the polygon later) I've try

var pattern = ctx.createPattern(img, 'no-repeat');

but it didn't work. Is there any way to achieve this?

Upvotes: 0

Views: 1820

Answers (1)

Mike
Mike

Reputation: 17932

In OpenLayers 3 and 4 you can create a pattern to fit the size the feature will occupy (similar to the gradient fitting the width in https://openlayers.org/en/v4.6.5/examples/canvas-gradient-pattern.html). This changes with resolution and needs a style function, which must be synchronous, so the image should be preloaded. In later versions it would be more complex as you would have to determine the 512 pixel origin OpenLayers will use instead of the feature's extent and pad or crop the pattern accordingly.

<!DOCTYPE html>
<html>
  <head>
    <title>Styling feature with CanvasGradient or CanvasPattern</title>
    <link rel="stylesheet" href="https://openlayers.org/en/v4.6.5/css/ol.css" type="text/css">
    <!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
    <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
    <script src="https://openlayers.org/en/v4.6.5/build/ol.js"></script>
    <style>
      #map {
        background: #ccc;
      }
    </style>
  </head>
  <body>
    <div id="map" class="map"></div>
    <script>

      var flagStyle = function(feature, resolution) {
        var pattern;
        var img = feature.get('flag');
        if (img) {
          var cnv1 = document.createElement('canvas');
          var ctx1 = cnv1.getContext('2d');

          // Patterns are in canvas pixel space, so we adjust for the
          // renderer's pixel ratio
          var pixelRatio = ol.has.DEVICE_PIXEL_RATIO;

          var extent = feature.getGeometry().getExtent();
          var width = ol.extent.getWidth(extent) / resolution * pixelRatio;
          var height = ol.extent.getHeight(extent) / resolution * pixelRatio;
          if (width >= 1 && height >= 1) {
            cnv1.width = width;
            cnv1.height = height;
            ctx1.drawImage(img, 2, 12, 60, 40, 0, 0, width, height);

            var cnv2 = document.createElement('canvas');
            var ctx2 = cnv2.getContext('2d');
            pattern = ctx2.createPattern(cnv1, 'no-repeat');
          }
        }
        return new ol.style.Style({
          fill: new ol.style.Fill({
            color: pattern
          })
        });
      };

      // Create a vector layer that makes use of the style function above…
      var vectorLayer = new ol.layer.Vector({
        source: new ol.source.Vector({
          url: 'https://openlayersbook.github.io/openlayers_book_samples/assets/data/countries.geojson',
          format: new ol.format.GeoJSON()
        }),
        style: flagStyle
      });

      vectorLayer.getSource().on('addfeature', function(event) {
        var feature = event.feature;
        var img = new Image();
        img.onload = function() {
          feature.set('flag', img);
        }
        img.src = 'https://www.countryflags.io/' +
          feature.get('iso_a2').toLowerCase() + '/flat/64.png';
      });

      var map = new ol.Map({
        layers: [
          vectorLayer
        ],
        target: 'map',
        view: new ol.View({
          center: ol.proj.fromLonLat([7, 52]),
          zoom: 3
        })
      });
    </script>
  </body>
</html>

Upvotes: 1

Related Questions