Icon Sprites with WebGL

This example uses OpenLayers v4.0.1. The latest is v.

#### Icon Sprites with WebGL

Icon sprite with WebGL

In this example a sprite image is used for the icon styles. Using a sprite is required to get good performance with WebGL.

Related API documentation:

- ol.Feature
,
- ol.Map
,
- ol.View
,
- ol.geom.Point
,
- ol.layer.Vector
,
- ol.source.Vector
,
- ol.style.Icon
,
- ol.style.Style

Copy Edit
Icon Sprites with WebGL Icon sprite with WebGL var iconInfo = [{ offset: [0, 0], opacity: 1.0, rotateWithView: true, rotation: 0.0, scale: 1.0, size: [55, 55] }, { offset: [110, 86], opacity: 0.75, rotateWithView: false, rotation: Math.PI / 2.0, scale: 1.25, size: [55, 55] }, { offset: [55, 0], opacity: 0.5, rotateWithView: true, rotation: Math.PI / 3.0, scale: 1.5, size: [55, 86] }, { offset: [212, 0], opacity: 1.0, rotateWithView: true, rotation: 0.0, scale: 1.0, size: [44, 44] }]; var i; var iconCount = iconInfo.length; var icons = new Array(iconCount); for (i = 0; i < iconCount; ++i) { var info = iconInfo[i]; icons[i] = new ol.style.Icon({ offset: info.offset, opacity: info.opacity, rotateWithView: info.rotateWithView, rotation: info.rotation, scale: info.scale, size: info.size, src: 'https://openlayers.org/en/v4.0.1/examples/data/Butterfly.png' }); } var featureCount = 50000; var features = new Array(featureCount); var feature, geometry; var e = 25000000; for (i = 0; i < featureCount; ++i) { geometry = new ol.geom.Point( [2 * e * Math.random() - e, 2 * e * Math.random() - e]); feature = new ol.Feature(geometry); feature.setStyle( new ol.style.Style({ image: icons[i % (iconCount - 1)] }) ); features[i] = feature; } var vectorSource = new ol.source.Vector({ features: features }); var vector = new ol.layer.Vector({ source: vectorSource }); var map = new ol.Map({ renderer: /** @type {ol.renderer.Type} */ ('webgl'), layers: [vector], target: document.getElementById('map'), view: new ol.View({ center: [0, 0], zoom: 5 }) }); var overlayFeatures = []; for (i = 0; i < featureCount; i += 30) { var clone = features[i].clone(); clone.setStyle(null); overlayFeatures.push(clone); } new ol.layer.Vector({ map: map, source: new ol.source.Vector({ features: overlayFeatures }), style: new ol.style.Style({ image: icons[iconCount - 1] }) }); map.on('click', function(evt) { var info = document.getElementById('info'); info.innerHTML = 'Hold on a second, while I catch those butterflies for you ...'; window.setTimeout(function() { var features = []; map.forEachFeatureAtPixel(evt.pixel, function(feature) { features.push(feature); return false; }); if (features.length === 1) { info.innerHTML = 'Got one butterfly'; } else if (features.length > 1) { info.innerHTML = 'Got ' + features.length + ' butterflies'; } else { info.innerHTML = 'Couldn\'t catch a single butterfly'; } }, 1); }); map.on('pointermove', function(evt) { if (evt.dragging) { return; } var pixel = map.getEventPixel(evt.originalEvent); var hit = map.hasFeatureAtPixel(pixel); map.getTarget().style.cursor = hit ? 'pointer' : ''; }); <div id="map" class="map"></div> <div id="info">&nbsp;</div>

    <!DOCTYPE html>
    <html>
      <head>
        <title>Icon Sprites with WebGL</title>
        <link rel="stylesheet" href="https://openlayers.org/en/v4.0.1/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.0.1/build/ol.js"></script>
      </head>
      <body>
        <div id="map" class="map"></div>
        <div id="info">&nbsp;</div>
        <script>
          var iconInfo = [{
            offset: [0, 0],
            opacity: 1.0,
            rotateWithView: true,
            rotation: 0.0,
            scale: 1.0,
            size: [55, 55]
          }, {
            offset: [110, 86],
            opacity: 0.75,
            rotateWithView: false,
            rotation: Math.PI / 2.0,
            scale: 1.25,
            size: [55, 55]
          }, {
            offset: [55, 0],
            opacity: 0.5,
            rotateWithView: true,
            rotation: Math.PI / 3.0,
            scale: 1.5,
            size: [55, 86]
          }, {
            offset: [212, 0],
            opacity: 1.0,
            rotateWithView: true,
            rotation: 0.0,
            scale: 1.0,
            size: [44, 44]
          }];

          var i;

          var iconCount = iconInfo.length;
          var icons = new Array(iconCount);
          for (i = 0; i < iconCount; ++i) {
            var info = iconInfo[i];
            icons[i] = new ol.style.Icon({
              offset: info.offset,
              opacity: info.opacity,
              rotateWithView: info.rotateWithView,
              rotation: info.rotation,
              scale: info.scale,
              size: info.size,
              src: 'https://openlayers.org/en/v4.0.1/examples/data/Butterfly.png'
            });
          }

          var featureCount = 50000;
          var features = new Array(featureCount);
          var feature, geometry;
          var e = 25000000;
          for (i = 0; i < featureCount; ++i) {
            geometry = new ol.geom.Point(
                [2 * e * Math.random() - e, 2 * e * Math.random() - e]);
            feature = new ol.Feature(geometry);
            feature.setStyle(
                new ol.style.Style({
                  image: icons[i % (iconCount - 1)]
                })
            );
            features[i] = feature;
          }

          var vectorSource = new ol.source.Vector({
            features: features
          });
          var vector = new ol.layer.Vector({
            source: vectorSource
          });

          var map = new ol.Map({
            renderer: /** @type {ol.renderer.Type} */ ('webgl'),
            layers: [vector],
            target: document.getElementById('map'),
            view: new ol.View({
              center: [0, 0],
              zoom: 5
            })
          });

          var overlayFeatures = [];
          for (i = 0; i < featureCount; i += 30) {
            var clone = features[i].clone();
            clone.setStyle(null);
            overlayFeatures.push(clone);
          }

          new ol.layer.Vector({
            map: map,
            source: new ol.source.Vector({
              features: overlayFeatures
            }),
            style: new ol.style.Style({
              image: icons[iconCount - 1]
            })
          });

          map.on('click', function(evt) {
            var info = document.getElementById('info');
            info.innerHTML =
                'Hold on a second, while I catch those butterflies for you ...';

            window.setTimeout(function() {
              var features = [];
              map.forEachFeatureAtPixel(evt.pixel, function(feature) {
                features.push(feature);
                return false;
              });

              if (features.length === 1) {
                info.innerHTML = 'Got one butterfly';
              } else if (features.length > 1) {
                info.innerHTML = 'Got ' + features.length + ' butterflies';
              } else {
                info.innerHTML = 'Couldn\'t catch a single butterfly';
              }
            }, 1);
          });

          map.on('pointermove', function(evt) {
            if (evt.dragging) {
              return;
            }
            var pixel = map.getEventPixel(evt.originalEvent);
            var hit = map.hasFeatureAtPixel(pixel);
            map.getTarget().style.cursor = hit ? 'pointer' : '';
          });
        </script>
      </body>
    </html>