React Displaying Heat Imagery
The Ignite UI for React map control has the ability to show heat-map imagery through the use of the ShapeFileRecord
that are generated by a IgrShapeDataSource
by loading geo-spatial data by loading shape files to a tile series.
It is highly recommended that you review the Binding Shape Files with Geo-Spatial Data topic as a pre-requisite to this topic.
React Displaying Heat Imagery Example
When a IgrShapeDataSource
loads its shape files, it converts that data into IgrShapefileRecord
objects. These objects can be retrieved from the GetPointData()
method of the IgrShapeDataSource
and can then be used to create a heat-map through usage of a IgrTileGeneratorMapImagery
object with a IgrHeatTileGenerator
assigned to its TileGenerator
property. This IgrTileGeneratorMapImagery
can then be used in a IgrGeographicTileSeries
as its tileImagery
source.
The IgrHeatTileGenerator
object works such that it has three value paths, xValues
, yValues
and values
. As an example of how these could be used, in the case of a shape file that has information about population, you could consider the xValues
to be longitude, yValues
to be latitude, and values
to be the population data. Each of these properties takes a number[]
.
The display of the geographic tile series when using the heat-map functionality can be customized by setting the minimumColor
and maximumColor
properties to "rgba" strings that describe colors that you wish to correspond to the minimum and maximum values of the collection that you assign to the values
property of the HeatTileGenerator.
You can further customize this by setting the ScaleColors
property of the generator to contain a collection of strings that describe colors, as this will tell the IgrHeatTileGenerator
what colors to use for the displayed values in the map. It is also possible to customize how colors in your ScaleColors
collection blur together by using the blurRadius
, maxBlurRadius
, and useBlurRadiusAdjustedForZoom
properties.
The IgrHeatTileGenerator
can also use a logarithmic scale. If you want to use this, you can set the useLogarithmicScale
property to true.
Web Worker
The IgrHeatTileGenerator
also has support for web workers to do the heavy lifting of the loading of the tile imagery from your shape file on a separate thread. This can greatly improve the performance of your geographic map when using the heat-map functionality. In order to use a web worker with the generator, you can set the useWebWorkers
property to true and then set the webWorkerInstance
property to an instance of your web worker.
// heatworker.worker.ts
import { HeatTileGeneratorWebWorker } from 'igniteui-react-core';
let worker: Worker = self as any;
worker.onmessage = HeatTileGeneratorWebWorker.onmessage;
HeatTileGeneratorWebWorker.postmessage = postMessageFunction;
HeatTileGeneratorWebWorker.start();
function postMessageFunction() {
self.postMessage.apply(self, Array.prototype.slice.call(arguments));
}
export default {} as typeof Worker & (new () => Worker);
Dependencies
import Worker from "./heatworker.worker"
import { IgrGeographicMapImagery } from 'igniteui-react-maps';
import { IgrHeatTileGenerator } from 'igniteui-react-core';
import { IgrGeographicMap } from 'igniteui-react-maps';
import { IgrGeographicMapModule } from 'igniteui-react-maps';
import { IgrGeographicTileSeries } from 'igniteui-react-maps';
import { IgrDataChartInteractivityModule } from 'igniteui-react-charts';
import { IgrTileGeneratorMapImagery } from 'igniteui-react-maps';
import { IgrShapeDataSource } from 'igniteui-react-core';
// ...
IgrDataChartInteractivityModule.register();
IgrGeographicMapModule.register();
Creating Heatmap
The following code snippet shows how to display a population based heat-map in the Ignite UI for React map component:
public map: IgrGeographicMap;
public tileImagery: IgrTileGeneratorMapImagery = null;
// ...
constructor(props: any) {
super(props);
this.onMapReferenced = this.onMapReferenced.bind(this);
this.onDataLoaded = this.onDataLoaded.bind(this);
this.tileImagery = new IgrTileGeneratorMapImagery();
this.state = { tileImagery: null }
}
public onMapReferenced(map: IgrGeographicMap) {
this.map = map;
const url = process.env.PUBLIC_URL;
const sds: IgrShapeDataSource = new IgrShapeDataSource();
sds.importCompleted = this.onDataLoaded;
sds.shapefileSource = url + "/Shapes/AmericanCities.shp";
sds.databaseSource = url + "/Shapes/AmericanCities.dbf";
sds.dataBind();
}
public onDataLoaded(sds: IgrShapeDataSource, e: any) {
let records = sds.getPointData();
let latArray: number[] = [];
let lonArray: number[] = [];
let popArray: number[] = [];
for (let r = 0; r < records.length; r++) {
let record = records[r];
for (let j = 0; j < record.points.length; j++) {
let points = record.points[j];
for (let k = 0; k < points.length; k++) {
latArray.push(points[k].y);
lonArray.push(points[k].x);
}
}
let value = parseInt(record.fieldValues["POP2010"], 10);
if (value >= 0) {
popArray.push(value);
} else {
popArray.push(0);
}
}
const gen = new IgrHeatTileGenerator();
gen.xValues = lonArray;
gen.yValues = latArray;
gen.values = popArray;
gen.blurRadius = 6;
gen.maxBlurRadius = 20;
gen.useBlurRadiusAdjustedForZoom = true;
gen.minimumColor = "rgba(100, 255, 0, 0.4)";
gen.maximumColor = "rgba(255, 255, 0, 0.95)";
gen.scaleColors = ["rgba(0, 0, 255, 64)", "rgba(0, 255, 255, 96)", "rgba(0, 255, 0, 160)", "rgba(255, 255, 0, 180)", "rgba(255, 0, 0, 200)"];
gen.useGlobalMinMax = true;
gen.useGlobalMinMaxAdjustedForZoom = true;
gen.useLogarithmicScale = true;
gen.useWebWorkers = true;
gen.webWorkerInstance = new Worker();
this.tileImagery.tileGenerator = gen;
this.setState({ tileImagery: this.tileImagery });
}
<IgrGeographicMap
ref={this.onMapReferenced}
height="100%"
width="100%" >
<IgrGeographicTileSeries
name="heatTiles"
tileImagery={this.state.tileImagery} />
</IgrGeographicMap>