Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions src/layers/Heat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {
setLayersOpacity,
makeHeatmapIntensity,
setLayersIntensity,
makeHeatmapRadius,
setLayersRadius,
} from '../utils/heat.js'
import { heatLayer } from '../utils/layers.js'
import Layer from './Layer.js'

class Heat extends Layer {
constructor(options) {
super(options)

this.createSource()
this.createLayers()
}

createLayers() {
const id = this.getId()
const { heatWeight, heatIntensity, heatColor, heatRadius, opacity } =
this.options
const isInteractive = false
const transformedIntensity = makeHeatmapIntensity(heatIntensity)
const transformedRadius = makeHeatmapRadius(heatRadius)

this.addLayer(
heatLayer({
id,
heatWeight,
heatIntensity: transformedIntensity,
heatColor,
heatRadius: transformedRadius,
opacity,
}),
{ isInteractive }
)
}

setOpacity(opacity) {
const mapgl = this.getMapGL()

if (mapgl) {
setLayersOpacity(mapgl, this.getId(), opacity)
}

this.options.opacity = opacity
}

setIntensity(heatIntensity) {
const mapgl = this.getMapGL()
const transformedIntensity = makeHeatmapIntensity(heatIntensity)

if (mapgl) {
setLayersIntensity(mapgl, this.getId(), transformedIntensity)
}

this.options.heatIntensity = transformedIntensity
}

setRadius(heatRadius) {
const mapgl = this.getMapGL()
const transformedRadius = makeHeatmapRadius(heatRadius)

if (mapgl) {
setLayersRadius(mapgl, this.getId(), transformedRadius)
}

this.options.heatRadius = heatRadius
}
}

export default Heat
2 changes: 2 additions & 0 deletions src/layers/layerTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import DonutCluster from './DonutCluster.js'
import EarthEngine from './EarthEngine.js'
import Events from './Events.js'
import GeoJson from './GeoJson.js'
import Heat from './Heat.js'
import LayerGroup from './LayerGroup.js'
import Markers from './Markers.js'
import ServerCluster from './ServerCluster.js'
Expand All @@ -24,6 +25,7 @@ export default {
events: Events, // event layer
geoJson: GeoJson, // tracked entity layer
group: LayerGroup, // tracked entity layer
heat: Heat, // event layer
markers: Markers, // facility layer
serverCluster: ServerCluster, // event layer
tileLayer: TileLayer, // basemap / external layer
Expand Down
38 changes: 38 additions & 0 deletions src/utils/heat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export const setLayersOpacity = (mapgl, id, heatOpacity) => {
mapgl
.getStyle()
.layers.filter(layer => layer.id.startsWith(id))
.forEach(layer => {
mapgl.setPaintProperty(layer.id, 'heatmap-opacity', heatOpacity)
})
}

export const makeHeatmapIntensity = (i = 0.5) => Math.pow(i, 2) * 2

export const setLayersIntensity = (mapgl, id, heatIntensity) => {
mapgl
.getStyle()
.layers.filter(layer => layer.id.startsWith(id))
.forEach(layer => {
mapgl.setPaintProperty(layer.id, 'heatmap-intensity', heatIntensity)
})
}

export const makeHeatmapRadius = (r = 0.5) => [
'interpolate',
['linear'],
['zoom'],
7,
50 * r,
20,
1000 * r,
]

export const setLayersRadius = (mapgl, id, heatRadius) => {
mapgl
.getStyle()
.layers.filter(layer => layer.id.startsWith(id))
.forEach(layer => {
mapgl.setPaintProperty(layer.id, 'heatmap-radius', heatRadius)
})
}
30 changes: 30 additions & 0 deletions src/utils/layers.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,33 @@ export const clusterCountLayer = ({ id, color, opacity }) => ({
'text-opacity': opacity ?? textOpacity,
},
})

// Layer with heat surface
export const heatLayer = ({
id,
heatWeight = 1,
heatIntensity = 0.5,
heatColor,
heatRadius,
opacity = 1,
source,
}) => ({
id: `${id}-heat`,
type: 'heatmap',
source: source || id,
paint: {
// Increase the heatmap weight based on frequency and property magnitude
'heatmap-weight': heatWeight,
// Increase the heatmap color weight weight by zoom level
// heatmap-intensity is a multiplier on top of heatmap-weight
'heatmap-intensity': heatIntensity,
// Color ramp for heatmap. Domain is 0 (low) to 1 (high).
// Begin color ramp at 0-stop with a 0-transparency color
// to create a blur-like effect.
'heatmap-color': heatColor,
// Adjust the heatmap radius by zoom level
'heatmap-radius': heatRadius,
// Transition from heatmap to circle layer by zoom level
'heatmap-opacity': opacity,
},
})
Loading