Here is how ended up doing it:
var features = vectorLayer.getSource().getFeatures();
var dotDensityFeature = [];
for (var i = 0; i < features.length; i++) {
var bounds = features[i].getGeometry().getExtent();
// Get the Center of the feature
var x0 = bounds[0] + (bounds[2] - bounds[0]) / 2;
var y0 = bounds[1] + (bounds[3] - bounds[1]) / 2;
var w = bounds[2] - bounds[0];
var h = bounds[3] - bounds[1];
for (var j = 0; j < features[i].getProperties()["NumOfDots"]; j ++) {
// Plot the dots around the center that way they'll be contained inside the feature
var x = parseInt(x0 + Math.random() * (w/8));
var y = parseInt(y0 + Math.random() * (h/8));
var newFeature = features[i].clone();
newFeature.setGeometry(new ol.geom.Point([x, y]));
newFeature.setStyle(new ol.style.Style({
image: new ol.style.Circle({
fill: new ol.style.Fill({ color: 'red' }),
stroke: new ol.style.Stroke({ color: 'black', width: '0.5' }),
radius: 2,
})
}));
dotDensityFeature.push(newFeature);
}
}
var dotDensityLayer = new ol.layer.Vector({
source: new ol.source.Vector({ features: dotDensityFeature }),
});
map.addLayer(dotDensityLayer);
For me it needs to be triggered off a button click but should work otherwise also. @Ian Turton solution also work if you don't have the restriction of the number of dots you want to show in each feature.