text arcgis for js 4.x集成热力图
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了text arcgis for js 4.x集成热力图相关的知识,希望对你有一定的参考价值。
## arcgis for js 4.x集成热力图
#### 主要步骤
1. [引入热力图插件 heatmap.js](#wendang)
2. [引入arcgis for js热力图集成工具](#tools)
3. [创建热力图图层](#create)
4. [获取数据,生成热力图](#getData)
5. [API](#API)
---
##### <span id="wendang">一、引入热力图插件 heatmap.js</span>
相关文档地址
[github-heatmap](https://github.com/pa7/heatmap.js)
[官方网站](https://www.patrick-wied.at/static/heatmapjs/)
[CSDN相关资料](http://blog.csdn.net/rongchaoliu/article/details/47830799)
---
##### <span id="tools">二、引入arcgis for js热力图集成工具</span>
~~~JavaScript
var HeartMapLayer;
function initHeartMapLayer(createHeatMapLayer) {
require([
"esri/layers/BaseDynamicLayer",
"esri/request"
], function (
BaseDynamicLayer, esriRequest
) {
HeartMapLayer = BaseDynamicLayer.createSubclass({
properties: {},
heatMap: null,
// 构造方法
constructor: function (properties) {
dojo.safeMixin(this.properties, properties);
//设置图层的ID
id : properties.id || null,
// 热力图创建所在的view
this._view = this.properties.view;
// 最终数据存储
this.lastData = [];
// 热力图所在dom
this.domNode = document.getElementById(this.properties.domNodeId);
// 初始化参数
this.config = {
container : this.domNode,
width: this._view.width,
height: this._view.height,
radius: 40,
debug: false,
visible: true,
useLocalMaximum: false,
gradient: {
0.45: "rgb(000,000,255)",
0.55: "rgb(000,255,255)",
0.65: "rgb(000,255,000)",
0.95: "rgb(255,255,000)",
1.00: "rgb(255,000,000)"
}
};
// 创建热力图
this.heatMap = h337.create(this.config);
// loaded
this.loaded = true;
// this.onLoad(this);
// global maximum value
this.globalMax = 0;
//添加视图resize事件,调整heatmap尺寸
// view.on("resize", function (event) {
// this.resizeHeatmap(event);
// });
dojo.connect(this._view, "onresize", this, this.resizeHeatmap);
// heatlayer div styling
this.domNode.style.position = 'relative';
this.domNode.style.display = 'none';
//TODO 绑定图层移除事件,待完善(延迟执行不确定性太多,但是未找到方法)
this.on("layerview-destroy", function (event) {
setTimeout(function (layer) {
layer.view.map.add(layer);
}, 500, this);
});
},
resizeHeatmap: function (event) {
var width = event.width;
var height = event.height;
//设置画布宽高
this.heatMap._renderer.setDimensions(width, height);
// 设置热力图容器的宽高
dojo.style(this.domNode, {
"width": width + 'px',
"height": height + 'px'
});
// set width and height of canvas element inside of container
var child = dojo.query(':first-child', this.domNode);
if (child) {
child.attr('width', width);
child.attr('height', height);
}
},
//将转换后的数据设置到热力图
storeHeatmapData: function (heatPluginData) {
// 设置热力图的数据
this.heatMap.setData(heatPluginData);
},
// 按照热力图插件的数据格式转换数据
convertHeatmapData: function (parsedData) {
var xParsed, yParsed, heatPluginData, dataPoint, screenGeometry;
// 设置热力图插件的数据对象
heatPluginData = {
max: parsedData.max,
data: []
};
if (parsedData.data) {
for (xParsed in parsedData.data) {
if (parsedData.data.hasOwnProperty(xParsed)) {
// for all y values and count
for (yParsed in parsedData.data[xParsed]) {
if (parsedData.data[xParsed].hasOwnProperty(yParsed)) {
// 将经纬度作为转为屏幕XY坐标
screenGeometry = view.toScreen(parsedData.data[xParsed][yParsed].dataPoint);
// 将格式化后的数据放入数据集中
heatPluginData.data.push({
x: screenGeometry.x,
y: screenGeometry.y,
value: parsedData.data[xParsed][yParsed].heatValue // count value of x,y
});
}
}
}
}
}
//将格式化后的数据设置到热力图并渲染
this.storeHeatmapData(heatPluginData);
},
// 格式化数据,并获取最大值
parseHeatmapData: function (features) {
// variables
var i, parsedData, dataPoint, attributes;
// if data points exist
if (features) {
// create parsed data object
parsedData = {
max: 0,
data: []
};
if (!this.config.useLocalMaximum) {
parsedData.max = this.globalMax;
}
// 遍历每一个坐标点
for (i = 0; i < features.length; i++) {
// 获取电信系
dataPoint = features[i].geometry;
// dataPoint = esri.geometry.Point(features[i].geometry);
// 检查点是否有效
var validPoint = false;
// 如果不使用设置的最大值, 点是有效的
if (!this.config.useLocalMaximum) {
validPoint = true;
}
// 如果使用设置的最大值,要确保点在当前视图内
else if(this._view.extent.contains(dataPoint)){
validPoint = true;
}
if (validPoint) {
attributes = features[i].attributes;
if (!parsedData.data[dataPoint.x]) {
parsedData.data[dataPoint.x] = [];
}
// 如果X,Y数据未创建,则创建
if (!parsedData.data[dataPoint.x][dataPoint.y]) {
// 创建一个数据对象
parsedData.data[dataPoint.x][dataPoint.y] = {};
// 如果热力图渲染属性在地图数据中存在,则使用地图数据
if (attributes && attributes.hasOwnProperty('heatValue')) {
parsedData.data[dataPoint.x][dataPoint.y].heatValue = attributes.heatValue;
} else {
parsedData.data[dataPoint.x][dataPoint.y].heatValue = 0;
}
}
// 渲染属性数据+1
parsedData.data[dataPoint.x][dataPoint.y].heatValue += 1;
// 添加经纬度点数据,用于下一步计算屏幕坐标
parsedData.data[dataPoint.x][dataPoint.y].dataPoint = dataPoint;
// 获取最大值
if (parsedData.max < parsedData.data[dataPoint.x][dataPoint.y].heatValue) {
parsedData.max = parsedData.data[dataPoint.x][dataPoint.y].heatValue;
if (!this.config.useLocalMaximum) {
this.globalMax = parsedData.data[dataPoint.x][dataPoint.y].heatValue;
}
}
}
}
//按照热力图插件所需的数据格式进一步转换数据
this.convertHeatmapData(parsedData);
}
},
// 设置数据
setData: function (features) {
// 设置地图的宽高
var event = {width : this._view.width, height : this._view.height}
this.resizeHeatmap(event);
// 设置数据
this.lastData = features;
// this.parseHeatmapData(features);
//重新描画图层,refresh方法在3D地图下无效,解决方案采用添加移除图层来解决
var viewType = this.view.type;
if (viewType == "3d") {
//TODO 移除图层,待完善(图层如果不在map中,如何处理?)
//该方法存在回调,移除后执行添加图层操作
this.view.map.remove(this);
} else {
// 重新描画图层(此方法在3D地图下无效)
this.refresh();
}
},
// 添加一个元素到热力图,并重新描画热力图
addDataPoint: function (feature) {
if (feature) {
// 将数据添加到最终数据
this.lastData.push(feature);
// 设置数据
setData(this.lastData);
}
},
// 返回生成热力图的数据集合
exportDataSet: function () {
return this.lastData;
},
// TODO 清除数据
clearData: function () {
//清除热力图的数据
this.heatMap.removeData();
// this.heatMap.clear();
var empty = [];
//设置热力图数据未[],并重新描画
this.setData(empty);
},
// 获取图片二进制数据
getImageUrl: function (extent, width, height) {
// 始终最终数据创建热力图
this.parseHeatmapData(this.lastData);
// 获取生成的热力图图片信息
var imageUrl = this.heatMap.getDataURL();
return imageUrl;
},
//图片预处理,将二进制数据转为图片
fetchImage : function (extent, width, height) {
var url = this.getImageUrl(extent, width, height);
return esriRequest(url, {
responseType: "image",
allowImageDataAccess: true
})
.then(function(response) {
var image = response.data;
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
//TODO 存在问题:width、height值为2048(原因不明),而热力图画板宽高为视图view宽高,直接放到视图则热力图会放大,计算宽高的差值,将热力图便宜解决上述问题
//计算X Y
var x = (width - this._view.width) / 2;
var y = (height - this._view.height) / 2;
context.drawImage(image, x, y, this._view.width, this._view.height);
return canvas;
}.bind(this));
}
});
createHeatMapLayer();
});
}
~~~
---
##### <span id="create">三、创建热力图图层</span>
1、视图创建完成之后执行,热力图初始化,并传入图层创建函数作为回调函数,热力图初始化完毕后创建热力图图层
~~~JavaScript
//初始化热力图,视图创建完毕后执行
initHeartMapLayer(createHeatMapLayer);
/**
* 创建热力图
*/
function createHeatMapLayer() {
heatLayer = new HeartMapLayer({
config: {
"useLocalMaximum": true,
"radius": 40,
"gradient": {
0.45: "rgb(000,000,255)",
0.55: "rgb(000,255,255)",
0.65: "rgb(000,255,000)",
0.95: "rgb(255,255,000)",
1.00: "rgb(255,000,000)"
}
},
id : "heatLayer",
"view": view,
"domNodeId": "heatLayer",
"opacity": 0.85
});
map.add(heatLayer);
}
~~~
---
##### <span id="getData">四、获取数据,生成热力图</span>
获取数据生成热力图,数据未arcgis点元素集合,调用setData函数设置数据,生成热力图
##### <span id="API">五、API</span>
Name | Parameter | Return Type | Summary
---|--- | ---|---
setData | [arcgis for js point元素集合](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Point.html) | 无 | 设置热力图数据,并刷新热力图图层
addDataPoint | [arcgis for js point元素](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Point.html) | 无 | 添加一个元素到热力图,并重新描画热力图
exportDataSet | 无 | [arcgis for js point元素集合](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-Point.html) | 返回生成热力图的数据
clearData | 无 | 无 | 清除热力图数据,并清除热力图
以上是关于text arcgis for js 4.x集成热力图的主要内容,如果未能解决你的问题,请参考以下文章
arcgis api 4.x for js 集成 Echarts4 实现模拟迁徙图效果(附源码下载)