环境
- ThreeJS 107版本
- three.min.js
- OrbitControls.js
- heatmap.min.js
说明
地球上添加热力图的原理是先生成平面的热力图,绘制在canvas上,再将canvas作为材质贴到地球球体上。可以实现色带配置,以及辐射范围。
解决方案
-
创建球的过程参见"ThreeJS制作地球"
-
创建热力图group
var gHeatmap = new THREE.Group();
- 使用heatmap.js库,创建heatmap对象
var heatmap = h337.create({
container: document.getElementById(_heatmapDomid),
512,//这里一定要2的n次方倍数,否则控制台报警告(定死,与后面坐标系计算强关联)
height: 256,//这里一定要2的n次方倍数,否则控制台报警告(定死,与后面坐标系计算强关联)
blur: '.8',
radius: _heatmapStyle.radius ? _heatmapStyle.radius : 10,//辐射圈范围大小e
alpha: true,
// opacity: 0.5,//透明度
// minOpacity: 0.1,
// maxOpacity: 0.9,
//色带配置(比例)
gradient: _heatmapStyle.gradient ? _heatmapStyle.gradient : { '.5': 'yellow', '.8': 'green', '.95': 'red' },
backgroundColor: 'rgba(0,102,256,0)'
//回调返回色带
// onExtremaChange: function (res) {
// console.log(res);
// }
});
- 构造热力图数据,构造对象数组,x、y、value的数据键值对,并计算出最大值(作为热力图值上限)
var max = 0;//最大值
var data = [];//数据源
for (var i = 0; i < _heatmapData.length; i++) {
//计算坐标,这里与canvas分辨率有关(不知为啥512*256分辨率下只能传整数??)
var coord = { x: ((_heatmapData[i].x + 180) / 360 * 512).toFixed(0), y: ((90 - _heatmapData[i].y) / 180 * 256).toFixed(0) };
data.push({ x: coord.x, y: coord.y, value: _heatmapData[i].value });
//计算最大值
max = max >= _heatmapData[i].value ? max : _heatmapData[i].value;
}
heatmap.setData({
max: max,
min: 0,
data: data
});
- 将生成的热力图canvas作为MeshLambertMaterial材质赋给地球
texture = new THREE.Texture(heatmap._renderer.canvas);
var material = new THREE.MeshLambertMaterial({
map: texture,
transparent: true,
opacity: 1
});
- 构造一个跟地球大小相同的球,将材质赋给这个球,添加到场景中
var mesh = new THREE.Mesh(new THREE.SphereGeometry(_earthOptions.earthBallSize, 50, 50), material);
gHeatmap.add(mesh);
scene.add(gHeatmap);
- 执行渲染
// 执行函数
function render() {
if (handle) {
cancelAnimationFrame(handle);
}
//是否开启了热力图,如开启则开启热力图渲染
if (texture) {
texture.needsUpdate = true;
}
renderer.clearDepth();
//自转
scene.rotation.y += _earthOptions.autorotationSpeed ? _earthOptions.autorotationSpeed : 0;
renderer.render(scene, camera);
orbitcontrols.update();
handle = requestAnimationFrame(render);
}