结合vue。
官方给出的热力图实例不满足需求要求在三维场景下展示,而官方的热力图仅支持MapView。
我这里的代码就是搬过来用的,但是,照搬的有问题,找了很有的原因原来是dojo里面的lang.hitch这个找不着,于是查阅了一些资料,这里参考的是这一篇
loadModules([
"dojo/_base/lang", //重要
"esri/Map",
"esri/views/MapView",
"esri/views/SceneView"
], option)
.then(([
lang,
Map, MapView,
SceneView
]) => {
const map = new Map({ //实例化地图
basemap: "satellite",
ground: "world-elevation",
logo: false
});
const view = new SceneView({ //实例化地图视图
container: "viewDiv",
map,
camera: {
position: {
x: 121.40105,
y: 31.40200,
z: 5000
},
tilt: 0
}
});
/**封装热力图*/
class HeatLayer {
constructor(obj) {
this.view = obj.view
this.config = obj.config
this.canvas = null
this.context = null
this.minnum = 1
this.maxnum = 1
this.visible = true
this.createCanvas()
}
/*创建Canvaslayer的容器canvas,添加到map的layers下面*/
createCanvas() {
let canvas = document.createElement('canvas');
canvas.width = this.view.width;
canvas.height = this.view.height;
canvas.setAttribute("id", "heatmap");
canvas.style.position = "absolute";
canvas.style.top = 0;
canvas.style.left = 0;
let parent = document.getElementsByClassName("esri-view-surface")[0];
parent.appendChild(canvas);
this.canvas = canvas;
this.context = document.getElementById("heatmap").getContext('2d');
this.startMapEventListeners()
}
/*转换数据*/
convertHeatmapData(data) {
var heatPluginData = [];
for (let i = 0; i < data.length; i++) {
let screenpoint = this.view.toScreen(new Point({
longitude: data[i][0],
latitude: data[i][1],
}));
//console.log(screenpoint)
// 判断数据是否带有权重,未带有权重属性是默认为1
if (data[0].length == 3) {
heatPluginData.push([Math.round(screenpoint.x), Math.round(screenpoint.y), data[i][2]]);
} else {
heatPluginData.push([Math.round(screenpoint.x), Math.round(screenpoint.y), 1]);
}
if (this.minnum > data[i][2]) {
this.minnum = data[i][2]
}
if (this.maxnum < data[i][2]) {
this.maxnum = data[i][2]
}
}
return {
points: heatPluginData,
min: this.minnum,
max: this.maxnum
};
}
//添加点数据
addPoint(data) {
this.data = data;
let points = this.convertHeatmapData(data);
//console.log(points)
points.points.forEach(point => {
this.context.beginPath();
let alpha = (point[2] - points.min) / (points.max - points.min);
this.context.globalAlpha = alpha;
this.context.arc(point[0], point[1], this.config.radius, 0, Math.PI * 2, true);
//绘制一个放射渐变样式的圆
let gradient = this.context.createRadialGradient(point[0], point[1], 0, point[0], point[1], this.config.radius);
gradient.addColorStop(0, 'rgba(0,0,0,1)');
gradient.addColorStop(1, 'rgba(0,0,0,0)');
this.context.fillStyle = gradient;
this.context.closePath();
this.context.fill();
});
this.MapColors();
//console.log('haol')
}
//设置渐变色带
getColorPaint() {
let paletteCanvas = document.createElement('canvas');
let paletteCtx = paletteCanvas.getContext('2d');
let gradientConfig = this.config.gradient;
paletteCanvas.width = 256
paletteCanvas.height = 1
let gradient = paletteCtx.createLinearGradient(0, 0, 256, 1);
for (let key in gradientConfig) {
gradient.addColorStop(key, gradientConfig[key])
}
paletteCtx.fillStyle = gradient;
paletteCtx.fillRect(0, 0, 256, 1);
return paletteCtx.getImageData(0, 0, 256, 1).data
}
//映射颜色
MapColors() {
let palette = this.getColorPaint();
let img = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height)
let imgData = img.data;
for (let i = 0; i < imgData.length; i++) {
let alpha = imgData[i];
let offset = alpha * 4;
if (!offset) {
continue
}
//映射颜色RGB值
imgData[i - 3] = palette[offset];
imgData[i - 2] = palette[offset + 1];
imgData[i - 1] = palette[offset + 2];
}
this.context.putImageData(img, 0, 0, 0, 0, this.canvas.width, this.canvas.height);
}
/*刷新layer*/
freshenLayer() {
this.clearCanvas();
this.addPoint(this.data);
}
/*清除渲染效果*/
clearCanvas() {
this.context.clearRect(0, 0, this.view.width, this.view.height);
}
/*添加监听*/
startMapEventListeners() {
let view = this.view;
view.watch("extent", lang.hitch(this, ()=>{
if (!this.visible) return;
this.freshenLayer();
//console.log('执行了吗')
}));
view.watch("camera", lang.hitch(this, ()=>{
if (!this.visible) return;
this.freshenLayer();
//console.log('执行了吗')
}));
}
}
//配置热力图的颜色、半径
var config = {
radius: 15,
gradient: {
'0.2':'rgba(0,0,255,0.2)',
'0.3':'rgba(43,111,231,0.3)',
'0.4':'rgba(2,192,241,0.4)',
'0.6':'rgba(44,222,148,0.6)',
'0.8':'rgba(254,237,83,0.8)',
'0.95':'rgba(255,118,50,0.9)',
'1':'rgba(255,64,28,1)'
}
};
//定时器,等地图初始化完成再绘制热力图,要不然找不到view,可以将定时器里面的内容放到view.when()内部
setTimeout(()=>{
var heatmap = new HeatLayer({
view,
config
});
heatmap.addPoint([["118.66124335378005","28.92588513213444",40],["118.08115584871544","29.04952406765118",66],["118.38722644164108","29.059406055009923",32],["118.41649535128697","29.135673493885232",80],["118.55019107002441","29.300640724771107",25],["118.57374080604751","28.685810835578355",76],["118.70453463048833","28.824715624332843",58],["118.86481914446486","28.946912041540134",67],["118.8727276271301","28.972530779387345",100]]);
},5000)
}).catch((err) => {
console.warn(err)
});
效果如: