Merge pull request #10101 from jahow/add-heatmap-hit-detection
Add hit detection support on the Heatmap layer
This commit is contained in:
@@ -220,6 +220,51 @@ class Heatmap extends VectorLayer {
|
|||||||
float alpha = smoothstep(0.0, 1.0, value) * v_weight;
|
float alpha = smoothstep(0.0, 1.0, value) * v_weight;
|
||||||
gl_FragColor = vec4(alpha, alpha, alpha, alpha);
|
gl_FragColor = vec4(alpha, alpha, alpha, alpha);
|
||||||
}`,
|
}`,
|
||||||
|
hitVertexShader: `
|
||||||
|
precision mediump float;
|
||||||
|
uniform mat4 u_projectionMatrix;
|
||||||
|
uniform mat4 u_offsetScaleMatrix;
|
||||||
|
uniform float u_size;
|
||||||
|
attribute vec2 a_position;
|
||||||
|
attribute float a_index;
|
||||||
|
attribute float a_weight;
|
||||||
|
attribute vec4 a_hitColor;
|
||||||
|
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
varying float v_weight;
|
||||||
|
varying vec4 v_hitColor;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
mat4 offsetMatrix = u_offsetScaleMatrix;
|
||||||
|
float offsetX = a_index == 0.0 || a_index == 3.0 ? -u_size / 2.0 : u_size / 2.0;
|
||||||
|
float offsetY = a_index == 0.0 || a_index == 1.0 ? -u_size / 2.0 : u_size / 2.0;
|
||||||
|
vec4 offsets = offsetMatrix * vec4(offsetX, offsetY, 0.0, 0.0);
|
||||||
|
gl_Position = u_projectionMatrix * vec4(a_position, 0.0, 1.0) + offsets;
|
||||||
|
float u = a_index == 0.0 || a_index == 3.0 ? 0.0 : 1.0;
|
||||||
|
float v = a_index == 0.0 || a_index == 1.0 ? 0.0 : 1.0;
|
||||||
|
v_texCoord = vec2(u, v);
|
||||||
|
v_hitColor = a_hitColor;
|
||||||
|
v_weight = a_weight;
|
||||||
|
}`,
|
||||||
|
hitFragmentShader: `
|
||||||
|
precision mediump float;
|
||||||
|
uniform float u_blurSlope;
|
||||||
|
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
varying float v_weight;
|
||||||
|
varying vec4 v_hitColor;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec2 texCoord = v_texCoord * 2.0 - vec2(1.0, 1.0);
|
||||||
|
float sqRadius = texCoord.x * texCoord.x + texCoord.y * texCoord.y;
|
||||||
|
float value = (1.0 - sqrt(sqRadius)) * u_blurSlope;
|
||||||
|
float alpha = smoothstep(0.0, 1.0, value) * v_weight;
|
||||||
|
if (alpha < 0.05) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_FragColor = v_hitColor;
|
||||||
|
}`,
|
||||||
uniforms: {
|
uniforms: {
|
||||||
u_size: function() {
|
u_size: function() {
|
||||||
return (this.get(Property.RADIUS) + this.get(Property.BLUR)) * 2;
|
return (this.get(Property.RADIUS) + this.get(Property.BLUR)) * 2;
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import HeatmapLayer from '../../../../src/ol/layer/Heatmap.js';
|
import HeatmapLayer from '../../../../src/ol/layer/Heatmap.js';
|
||||||
|
import Feature from '../../../../src/ol/Feature.js';
|
||||||
|
import Point from '../../../../src/ol/geom/Point.js';
|
||||||
|
import VectorSource from '../../../../src/ol/source/Vector.js';
|
||||||
|
import Map from '../../../../src/ol/Map.js';
|
||||||
|
import View from '../../../../src/ol/View.js';
|
||||||
|
|
||||||
describe('ol.layer.Heatmap', function() {
|
describe('ol.layer.Heatmap', function() {
|
||||||
|
|
||||||
@@ -12,4 +16,60 @@ describe('ol.layer.Heatmap', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('hit detection', function() {
|
||||||
|
|
||||||
|
it('hit detects two distinct features', function(done) {
|
||||||
|
const target = document.createElement('div');
|
||||||
|
target.style.width = '300px';
|
||||||
|
target.style.height = '300px';
|
||||||
|
document.body.appendChild(target);
|
||||||
|
|
||||||
|
const feature = new Feature({geometry: new Point([0, 0]), id: 1, weight: 10});
|
||||||
|
const feature2 = new Feature({geometry: new Point([14, 14]), id: 2, weight: 10});
|
||||||
|
|
||||||
|
const source = new VectorSource({
|
||||||
|
features: [feature, feature2]
|
||||||
|
});
|
||||||
|
const layer = new HeatmapLayer({
|
||||||
|
source: source,
|
||||||
|
blur: 10,
|
||||||
|
radius: 10
|
||||||
|
});
|
||||||
|
const map = new Map({
|
||||||
|
layers: [layer],
|
||||||
|
view: new View({
|
||||||
|
center: [0, 0],
|
||||||
|
resolution: 0.1
|
||||||
|
}),
|
||||||
|
target: target
|
||||||
|
});
|
||||||
|
map.renderSync();
|
||||||
|
|
||||||
|
function hitTest(coordinate) {
|
||||||
|
const features = map.getFeaturesAtPixel(
|
||||||
|
map.getPixelFromCoordinate(coordinate)
|
||||||
|
);
|
||||||
|
return features.length ? features[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
let res;
|
||||||
|
|
||||||
|
res = hitTest([0, 0]);
|
||||||
|
expect(res).to.be(feature);
|
||||||
|
res = hitTest([20, 0]);
|
||||||
|
expect(res).to.be(null);
|
||||||
|
res = hitTest([14, 14]);
|
||||||
|
expect(res).to.be(feature2);
|
||||||
|
res = hitTest([0, 14]);
|
||||||
|
expect(res).to.be(null);
|
||||||
|
|
||||||
|
document.body.removeChild(target);
|
||||||
|
done();
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user