環境
- 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),
width: 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);
}