vue3 + cesium + heatmapjs 开发热力图(不需要CesiumHeatMap插件)
第一步:需要install cesium和heatmapjs
npm install cesium heatmap.js
第二步:引入cesium和heatmap
import * as Cesium from "cesium";
import h337 from "heatmap.js";
import "cesium/Build/Cesium/Widgets/widgets.css";
import heatdata from "../assets/json/heatmap.json"; // 热力图数据
热力图数据举例,保存成json放到assets中
[{ "x": 122.0147, "y": 39.6146, "value": 12 },{ "x": 121.9923, "y": 39.6274, "value": 20 },{ "x": 121.9302, "y": 39.6561, "value": 30 },{ "x": 121.9611, "y": 39.6824, "value": 41 },{ "x": 122.0624, "y": 39.7273, "value": 19 },{ "x": 122.1903, "y": 39.7511, "value": 80 },{ "x": 122.0451, "y": 39.7352, "value": 30 },{ "x": 121.9766, "y": 39.8237, "value": 71 },{ "x": 121.6628, "y": 39.5401, "value": 62 },{ "x": 122.1329, "y": 39.7599, "value": 77 },{ "x": 121.9337, "y": 39.6685, "value": 98 },{ "x": 122.1068, "y": 39.6472, "value": 41 },{ "x": 121.9201, "y": 39.7086, "value": 89 }
]
第三步:初始化一个cesium viewer
const viewerContainer = ref(null); // Cesium Viewer 容器引用
let viewer; // Cesium Viewer 实例
const heatMapContainer = ref(null); // 热力图容器引用// onMounted 生命周期下给viewer赋值// 初始化 Cesium Viewerviewer = new Cesium.Viewer(viewerContainer.value, {imageryProvider: false,sceneMode: Cesium.SceneMode.SCENE2D,baseLayerPicker: false,animation: false,timeline: false,fullscreenButton: false,vrButton: false,creditContainer: null,geocoder: false,sceneModePicker: false,navigationHelpButton: false,terrainProvider: new Cesium.EllipsoidTerrainProvider()});// 设置相机初始视角viewer.camera.setView({destination: Cesium.Cartesian3.fromDegrees(121.74, 39.02, 50000),orientation: {heading: Cesium.Math.toRadians(0),pitch: Cesium.Math.toRadians(-30),roll: 0,},});
这是对应的div容器
<!-- Cesium 地图容器 --><div ref="viewerContainer" class="cesium-container"></div><!-- 热力图容器(隐藏),用于生成 canvas 图层,稍后贴图到 Cesium 上 --><divref="heatMapContainer"style="width: 10000px; height: 10000px; background-color: #00afff"v-show="false"></div>
第四步:构建两个热力图相关的方法
/*** 创建热力图* - 根据 heatdata 数据生成 h337 的 heatmap 图层(在隐藏 div 上)* - 映射经纬度到 canvas 像素坐标* - 返回 canvas 对象供贴图使用*/
function createHeatmap() {const points = []; // 存储转换后的热力点坐标(像素单位)let max = 100; // 最大值,控制颜色梯度const width = 10000; // 画布宽度(像素)const height = 10000; // 画布高度(像素)for (const item of heatdata) {// 将地理坐标映射到 canvas 像素空间const point = {x: Math.floor(((item.x - lonMin) / (lonMax - lonMin)) * width),y: Math.floor((Math.abs(item.y - latMax) / (latMax - latMin)) * height),value: Math.floor(item.value),radius: 1, // 热力点半径(越大扩散越广)};max = Math.max(max, item.value); // 更新最大值points.push(point);}// 创建 heatmap.js 实例,绑定在 heatMapContainer 上const heatmapInstance = h337.create({container: heatMapContainer.value,radius: 10,maxOpacity: 0.5,minOpacity: 0,blur: 0.75,});// 设置热力图数据(包含最大值和点数据)heatmapInstance.setData({max,data: points,});// 获取生成的 canvas 元素(heatmap-canvas 是 heatmap.js 自动生成的)const canvas = heatMapContainer.value.querySelector(".heatmap-canvas");return canvas; // 返回用于贴图的图层
}/*** 将热力图贴到 Cesium 地球表面* - 通过 rectangle 实体,把 canvas 作为纹理贴到指定的经纬度矩形范围*/
function applyHeatmapToCesium(canvas) {viewer.entities.add({name: "heatmap", // 实体名称rectangle: {// 贴图范围:这里是整个地球(会导致“太大”问题,可改为实际范围)coordinates: Cesium.Rectangle.fromDegrees(lonMin, latMin, lonMax, latMax),// 设置贴图材质为热力图 canvas,并开启透明通道material: new Cesium.ImageMaterialProperty({image: canvas, // 传入生成好的 canvastransparent: true, // 启用透明,保留 alpha 通道}),},});
}
第五步:在生命周期 onMounted 中使用热力图方法
// 创建热力图 Canvas 并贴图到 Cesium 地球上const canvas = createHeatmap(); // 🔥 创建热力图 canvasapplyHeatmapToCesium(canvas); // 📌 把它作为纹理贴到地球表面
最后效果