Cesium开发工具篇 | 05与第三方库的集成

集成Three.js

Three.js是基于原生WebGL封装运行的三维引擎库,在所有WebGL引擎中,Three.js是国内文资料最多、使用最广泛的三维引擎。Three.js可应用于Web 3D的可视化(如产品在线浏览、在线三维可视化等),H5/微信小程序游戏(如跳一跳),科教领域,机械领域,WebVR(VR看房、VR看车等)以及家装室内设计等方面,是一个比较轻量级的跨浏览器JavaScript库 ,适合在浏览器中创建和显示动画3D计算机图形。将Cesium的行星级渲染和GIS功能与Three.js广泛而易用的通用3D API相结合,为新的WebGL体验开启了许多可能性。两者的集成总体思路如下:
(1)创建两个容器,分别用于显示cesium和three的场景
(2)初始化cesium、three渲染器
(3)调整three和cesium的渲染频率保持一致
(4)调整three和cesium的相机位置角度保持一致
(5)加入要展示的图形
以下展示了部分核心代码。

 
// 2-1.初始化cesium // cesium初始化时,要将它的自动渲染关掉(即useDefaultRenderLoop属性调整为false) cesium.viewer = new Cesium.Viewer("cesiumContainer", { useDefaultRenderLoop: false, // 关闭自动渲染 ... }); // 2-2.初始化three function initThree() { let fov = 45; let width = window.innerWidth; let height = window.innerHeight; let aspect = width / height; let near = 1; let far = 10 * 1000 * 1000; // needs to be far to support Cesium's world-scale rendering three.scene = new THREE.Scene(); three.camera = new THREE.PerspectiveCamera(fov, aspect, near, far); three.renderer = new THREE.WebGLRenderer({ alpha: true }); ThreeContainer.appendChild(three.renderer.domElement); } // 3.调整three和cesium的渲染频率 // 手动开启cesium和three的渲染,并放进一个渲染频率里。 function loop() { requestAnimationFrame(loop); renderCesium(); renderThreeObj(); // 4.调整相机一致 // 这里使用的cesium的相机为主相机,使three的相机与cesium保持一致即可。 renderCamera(); } // 5.加入要展示的图形 // 这里加入一个cesium的图形polygon,再加入一个three的球体,以及一个three的12面体。 function init3DObject() { let entity = { name: "Polygon", polygon: { hierarchy: Cesium.Cartesian3.fromDegreesArray([ minWGS84[0], minWGS84[1], maxWGS84[0], minWGS84[1], maxWGS84[0], maxWGS84[1], minWGS84[0], maxWGS84[1], ]), material: Cesium.Color.RED.withAlpha(0.1), }, }; let Polypon = cesium.viewer.entities.add(entity); let doubleSideMaterial = new THREE.MeshNormalMaterial({ side: THREE.DoubleSide, }); geometry = new THREE.SphereGeometry(1, 32, 32); let sphere = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial({ color: 0xffffff, side: THREE.DoubleSide, }) ); //12面体 ... } }

效果图如下:


集成Echarts

Echarts 是一个基于 JavaScript 的开源可视化图表库,具有丰富的图表类型,可用于地理数据可视化的地图、热力图、线图等。Cesium通过与Echarts的地理数据可视化能力相结合,大大增强Cesium整体的可视化效果。本文通过封装EchartsLayer来实现迁徙图的效果。需要注意的是,在图表的option配置项中不需要写geo,同时每个series数组中元素都必须加coordinateSystem:'GLMap'。部分核心代码如下:

var EchartsLayer = function (map, options) {
  this._map = map;
  this._overlay = this._createChartOverlay();
  if (options) {
    this._registerMap();
  }
  this._overlay.setOption(options || {});
};

let _echartLayer = new EchartsLayer(viewer, option);

简单效果图如下所示:


集成heatmap

heatmap.js是一个轻量级的、最先进的用于表达热力图的可视化前端库,比如人群分布情况、污染物浓度变化情况、信号强度等。感兴趣的同学可以进入官网https://www.patrick-wied.at/static/heatmapjs/ 查看详情。
下面说一下cesium和heatmap集成的原理,其实也很简单,就是把使用heatmap.js生成的热力图,以贴图材质的方式赋给某个几何图形贴图属性。部分核心代码如下:


   // 根据热力图图片范围,生成随机热力点和强度值
   var dataRaw = [];
   for (var i = 0; i < len; i++) {
     var point = {
       lat: latMin + Math.random() * (latMax - latMin),
       lon: lonMin + Math.random() * (lonMax - lonMin),
       value: Math.floor(Math.random() * 100),
     };
     dataRaw.push(point);
   }
   // 生成数据
   for (var i = 0; i < len; i++) {
     var dataItem = dataRaw[i];
     var point = {
       x: Math.floor(((dataItem.lat - latMin) / (latMax - latMin)) * width),
       y: Math.floor(((dataItem.lon - lonMin) / (lonMax - lonMin)) * height),
       value: Math.floor(dataItem.value),
     };
     max = Math.max(max, dataItem.value);
     points.push(point);
   }

   // 创建热力图
   var heatmapInstance = h337.create({
     container: document.querySelector(".heatmap"),
   });

   var data = {
     max: max,
     data: points,
   };
   heatmapInstance.setData(data);

// 将热力图添加到球体上(生成的热力图canvas元素类名为heatmap-canvas)
   var canvas = document.getElementsByClassName("heatmap-canvas");
   // console.log(canvas);
   viewer.entities.add({
     name: "heatmap",
     rectangle: {
       coordinates: Cesium.Rectangle.fromDegrees(
         lonMin,
         latMin,
         lonMax,
         latMax
       ),
       material: new Cesium.ImageMaterialProperty({
         image: canvas[0],
         transparent: true,
       }),
     },
   });

效果图如下:


2.png

集成Turf

Cesium本身更侧重于三维可视化,在空间分析方面会显得薄弱些,当然空间分析能力可以借助开源postGIS中的函数去实现,然后将结果通过Cesium去呈现。这里我们不对postGIS进行介绍,而是给大家介绍一个轻量级的用于空间分析的前端库,即Turf。Turf的定位是地理空间分析库,处理各种地图算法;特点是离线计算、模块化、快速。下面是一个简单的示例:计算两点之间的距离。

var point1 = turf.point([144.834823, -37.771257]);
var point2 = turf.point([145.14244, -37.830937]);
var midpoint = turf.midpoint(point1, point2);

而下面的截图是通过Turf、Cesium实现的点、线、面缓冲区分析结果,即借助了Turf的空间分析能力和Cesium的可视化能力。


3.png

部分核心代码如下:

 // 初始化点缓冲
 function initPointBuffer() {
   let point = [106.422638966289, 29.5698367125623];
   addPoint(point);

   let pointF = turf.point(point);
   let buffered = turf.buffer(pointF, 60, { units: "meters" });
   let coordinates = buffered.geometry.coordinates;
   let points = coordinates[0];
   let degreesArray = pointsToDegreesArray(points);
   addBufferPolyogn(Cesium.Cartesian3.fromDegreesArray(degreesArray));
 }

 // 添加点
 function addPoint(point) {
   viewer.entities.add({
     position: Cesium.Cartesian3.fromDegrees(point[0], point[1], 0),
     point: {
       pixelSize: 10,
       heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
       color: Cesium.Color.YELLOW,
       outlineWidth: 3,
       outlineColor: Cesium.Color.YELLOW.withAlpha(0.4),
     },
   });
 }
 // 添加缓冲面
 function addBufferPolyogn(positions) {
   viewer.entities.add({
     polygon: {
       hierarchy: new Cesium.PolygonHierarchy(positions),
       material: Cesium.Color.RED.withAlpha(0.6),
       classificationType: Cesium.ClassificationType.BOTH,
     },
   });
 }

如果你觉得比较麻烦的话,网上也有大神基于cesium、turf、shpjs、proj4js等这些库文件封装好了CesiumVectorTile,GitHub地址为https://github.com/engineerhe/CesiumVectorTile,支持小数据量的geojson、shape文件矢量动态切片,并且还能实现贴地效果。
获取上述全部源代码可访问本人GitHub地址:https://github.com/ls870061011。

你可能感兴趣的:(Cesium开发工具篇 | 05与第三方库的集成)