I know that is possible to make a heatmap using ol/layer/Heatmap, but this component accept as source only ol/source/Vector component.

Someone have build a heatmap using VectorTile as source? Can you suggest me a workaround?


1 Answer 1


What @Mike proposed, to load vector tile features into normal vector heatmap layer is probably the only solution. Problem is that with vector tiles number of features can change greatly with zoom change, so with zoom change previous features in normal vector layer have to be cleared and new ones added.

One possible solution for this would be to use vector tile source method getFeaturesInExtent after all tiles are loaded, to get all features in visible extent and select the ones to be added to the heatmap vector layer. Vector tile features/geometries cannot be used directly, since they have different structure that normal vector features. Features for normal vector layer have to be created from coordinates of vector features.

Code below is more a proof of concept than bulletproof solution. Whole idea is to wait for map moveend events and vector tile layer postrender events. When moveend is detected, set a flag, and when a postrender event is detected and moveend flag is set, do inventory of vector tile layer features with the getFeaturesInExtent method, clear heatmap vector layer source and add desired features (points) from vector tile layer inventory.

Code uses ArcGIS World_Basemap_v2 vector tile layer as a source. For heatmap points cities are filtered in. Since cities in the layer have no property to be used as weight, each city gets the same value 0.8.

var defaultStyles = new ol.layer.Vector().getStyleFunction()();

var styleFunction = function(feature, resolution) {
  if (feature.get('layer') == 'Coastline') {

var vectorLayer = new ol.layer.VectorTile({
  source: new ol.source.VectorTile({
    format: new ol.format.MVT(),
    url: 'https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer/tile/{z}/{y}/{x}.pbf',
    wrapX: false
  style: styleFunction

var heatmapSource = new ol.source.Vector();

var heatmapLayer = new ol.layer.Heatmap({
  source: heatmapSource,
  weight: function(feature) {

var map = new ol.Map({
  target: 'map',
  view: new ol.View({
    center: [0, 0],
    zoom: 0,
    extent: vectorLayer.getSource().getTileGrid().getExtent()
  layers: [vectorLayer, heatmapLayer]
var moveEnd = false;
var firstTime = true;
map.on('moveend', function() {
  moveEnd = true;
  if (firstTime) {
    firstTime = false;
    setTimeout(function() {
    }, 250);

vectorLayer.on('postrender', function(evt) {
  if (moveEnd) {
    moveEnd = false;
    setTimeout(function() {
    }, 0);

function refreshHeatmap() {
  var geometry, extent, source, features;
  source = vectorLayer.getSource();
  features = source.getFeaturesInExtent(map.getView().calculateExtent());
  for (var i = 0; i < features.length; i++) {
    geometry = features[i].getGeometry();
    if ((geometry.getType() == 'Point') && (features[i].get('layer').substring(0, 4) == 'City')  && features[i].get('_name_en') )  {
      extent = geometry.getExtent();
      heatmapSource.addFeature(new ol.Feature({geometry: new ol.geom.Point([extent[0], extent[1]])}));

Here is working JSFiddle: https://jsfiddle.net/TomazicM/y1xus3m0/ and two screenshots at different zooms:

enter image description here

enter image description here

  • You can get vector tile features with standard geometries by specifying new ol.format.MVT({featureClass: ol.Feature})
    – Mike
    Dec 16, 2021 at 9:40
  • @Mike If I want to use some features (points) for heatmap and some features (polygons) for actual display in vector tile layer (as in the above example), would this be OK for vector tile layer features?
    – TomazicM
    Dec 16, 2021 at 9:46
  • It would work jsfiddle.net/hmtofbrw The rendering of the vector tiles might be less efficient with standard features, but the cities could be used directly in the heatmap
    – Mike
    Dec 16, 2021 at 10:02
  • @Mike Good to know, thanks!
    – TomazicM
    Dec 16, 2021 at 10:05

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.