# Making heatmap points full opacity regardless of weight using OpenLayers

As shown in this example, when the blur is set to 0, the opacity of each point correlates to the weight, and the opacity parameter is layered on top of the weight opacity.

Here is an example image of the opacity corresponding to point weight: How do I make all the points full opacity regardless of weight and layering?

Here is my current heatmap object:

``````const rainbow = [
'rgba(127.5, 0.0, 255.0, 1.0)',
'rgba(0.4999999999999982, 180.8667334394926, 235.43872205689976, 1.0)',
'rgba(128.5, 254.99516197392535, 179.75601446106756, 1.0)',
'rgba(255.0, 178.63847458628922, 96.49481776078913, 1.0)',
'rgba(255.0, 3.122849337825751e-14, 1.5614246689128753e-14, 1.0)',
]

const heatmapLayer = new ol.layer.Heatmap({
source: vectorSource,
blur: 1,
weight: function() {
return 0.1;
},
});
``````

There seems to be no option or method to set point opacity in `ol.layer.Heatmap` layer to 1, regardless of weight.

One possible solution would be to use `ol.layer.Raster` layer to manipulate pixels of `ol.layer.Heatmap` layer. Problem is that raster layer requires image layer as input, which `ol.layer.Heatmap` layer is not.

So one possible solution that works is to use `ol.layer.VectorImage` layer to create vector layer with points that have opacity set to values below 1 (color is not important), and then use `ol.layer.Raster` layer to manipulate pixels of that layer.

Logic of this solution goes like this:

1. Lets's say there are `n` colors for the heat map colors `rainbow`.
2. Create `ol.layer.VectorImage` vector layer, styling points with circles that have opacity set to `1/n` (color is not important). When circles will overlap, resultant opacity will increase proportionally with the number of overlaps. Layer is not added to the map.
3. Create `ol.layer.Raster` layer, taking `ol.layer.VectorImage` layer as input. Layer is used for pixel manipulation. In option `operation` opacity of input pixels (value range is 0 to 255) is divided in `n + 1` classes using simple formula `colorIndex = Math.round(opacity / (255 / n)`.
4. Index from previous step is used to get corresponding color from `rainbow` array. This is then returned in `operation` function as pixel color.
5. One extra thing to be taken into account is that individual circle, created by `ol.layer.VectorImage` layer, does not have uniform opacity, because it fades (decreases) a bit at the edge for smoothing purposes. This is important for nonoverlapped circles which get the first color. For this reason extra color is added at the beginning, being copy of the first actual color, just with half of the opacity.

So code for earthquake heatmap could then look something like this (with gradient colors from your question):

``````const n = 5;

var vectorLayer = new ol.layer.VectorImage({
source: new ol.source.Vector({
url: 'data/2012_Earthquakes_Mag5.kml',
format: new ol.format.KML({
extractStyles: false,
}),
}),
style: function (feature, resolution) {
var style = new ol.style.Style({
image: new ol.style.Circle({
fill: new ol.style.Fill({
color: 'rgba(255, 0, 0,' + (1 / n) + ')'
})
})
});
return(style);
},
});

function heat(pixels, data) {
const rainbow = [
[127.5, 0.0, 255.0, 125],
[127.5, 0.0, 255.0, 255],
[0.4999999999999982, 180.8667334394926, 235.43872205689976, 255],
[128.5, 254.99516197392535, 179.75601446106756, 255],
[255.0, 178.63847458628922, 96.49481776078913, 255],
[255.0, 3.122849337825751e-14, 1.5614246689128753e-14, 255]
];
var pixel = pixels;
if (pixel) {
var colorIndex = Math.floor(pixel / (255 / n));
pixel = rainbow[colorIndex];
}
return pixel;
}

var rasterSource = new ol.source.Raster({
sources: [vectorLayer],
operation: heat
});

var rasterLayer = new ol.layer.Image({
source: rasterSource
});

var baseLayer = new ol.layer.Tile({
source: new ol.source.Stamen({
layer: 'toner',
}),
});

new ol.Map({
layers: [baseLayer, rasterLayer],
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 2,
}),
});
``````

Heatmap then looks like this: • Thank you so much! Sorry for the slow reply, I still have some questions though: (1) Could you explain a bit how the heat function works? Specifically the part about `pixel / 51`. (2) The map is also very slow to drag around and zoom, is this a characteristic of raster layers in general? (3) The colour array `rainbow` was originally passed to the to the `gradient` parameter, so here there are only 5 colours available, how could this be worked around other than just adding more colour intervals? Thanks again! Jul 12, 2021 at 13:15
• If answer helped you solve your problem, it's customary on GIS SE site to mark it as accepted, to let other users with similar questions/problems know that problem was resolved. As for (1) and (3), I'll ad some explanation, as for (2) I cannot tell why your map is slow since I don't know how it's layers are defined/structured. The example from the image above worked without any problems. Jul 12, 2021 at 13:59
• Marked as accepted! (2) The only layers I used were the ones shown in your answer, were you able to drag and zoom without the map lagging and having to refresh? Jul 12, 2021 at 14:39
• See modified answer. Jul 13, 2021 at 10:15