1.鼠标点击添加点和线
handler.setInputAction(function(event){//返回地球表面上的点坐标const earthPosition = positionUtil.cartesian2ToCartesian3(event.position)if(Cesium.defined(earthPosition)){const ellipsoid = viewer.scene.globe.ellipsoid;const cartographic = ellipsoid.cartesianToCartographic(earthPosition);const lon = Cesium.Math.toDegrees(cartographic.longitude);const lat = Cesium.Math.toDegrees(cartographic.latitude);const alt = cartographic.height +20// 高度加20AddPoint({
lon,
lat,
alt,color: Cesium.Color.YELLOW}, viewer);
positions.push(Cesium.Cartesian3.fromDegrees(lon, lat, alt))
positons2.push({x:lon,y:lat,z:alt})if(positions.length >=2){if(!polyline)
polyline =AddPolyline(viewer)}}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);// 添加点constAddPoint=(params, viewer)=>{constentity:any =newCesium.Entity({id:`${params.lon}点`,name:'点',show:true,position: Cesium.Cartesian3.fromDegrees(params.lon, params.lat, params.alt),point:newCesium.PointGraphics({show:true,//是否展示pixelSize:10,//点大小color: params.color
})});//收集Id
viewer.entities.add(entity);return entity;}// 添加线constAddPolyline=(viewer)=>{const entity =newCesium.Entity({id:`${newDate().getTime()}线`,name:'线',polyline:newCesium.PolylineGraphics({show:true,clampToGround:false,positions:newCesium.CallbackProperty(function(){return positions;},false),//params.positions,width:10,material:newCesium.PolylineGlowMaterialProperty({glowPower:0.2,color: Cesium.Color.BLUE})})}as any);
viewer.entities.add(entity);return entity;}
2.右键结束绘制时,计算折线中心点和绘制方向;折线中心点可以替换为模型中心点,这样就会看着这个点飞行;计算方向主要是判断绘制的顺序是顺时针绘制的还是逆时针绘制的
handler.setInputAction(function(event){// 计算折线中心点
centerPos =caclPolyCenter(viewer)
isRight =_judgeDirection(positions)// console.log(isRight, '逆时针');if(handler){
handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);}}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)constcaclPolyCenter=(viewer)=>{const entity =newCesium.Entity({name:"Red polygon on surface",polygon:{hierarchy:newCesium.PolygonHierarchy(positions),material: Cesium.Color.RED.withAlpha(0.5),},});const polyPositions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions;let polyCenter = Cesium.BoundingSphere.fromPoints(polyPositions).center;//中心点
polyCenter = Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter);const cartographic = Cesium.Cartographic.fromCartesian(polyCenter, viewer.scene.globe.ellipsoid,newCesium.Cartographic());const lat = Cesium.Math.toDegrees(cartographic.latitude);const lng = Cesium.Math.toDegrees(cartographic.longitude);const height = cartographic.height;return{x: lng,y: lat,z: height}}/**
* 判断点的顺序是顺时针还是逆时针
* @param {Cesium.Cartesian3[]} points
*/const_judgeDirection=(points)=>{const lonlat1 = Cesium.Cartographic.fromCartesian(points[0])const lonlat2 = Cesium.Cartographic.fromCartesian(points[1])const lonlat3 = Cesium.Cartographic.fromCartesian(points[2])const x1 = lonlat1.longitude,
y1 = lonlat1.latitude,
x2 = lonlat2.longitude,
y2 = lonlat2.latitude,
x3 = lonlat3.longitude,
y3 = lonlat3.latitude,
dirRes =(x2 - x1)*(y3 - y2)-(y2 - y1)*(x3 - x2)const isR = dirRes >0return isR
}
3.点击飞行
pitch默认为-5
setExtentTime: 在viewer的clock中设置时间间隔,flytime默认为15,也可以根据线段的长度来定义每一段的飞行时间
TimeExecution: 添加clock.onTick事件监听,每一帧调用,根据时间动态计算下一个点的坐标,然后更新相机位置.关于viewer.clock.onTick可查看api深入学习
changeCameraHeading: 如果当前的时间=设定的停止时间,移除监听并开始转向,当前时间=设定的停止时间时,开始下一段线的飞行marksIndex+1
constflyExtent=(viewer)=>{// 相机看点的角度,如果大于0那么则是从地底往上看,所以要为负值const pitch = Cesium.Math.toRadians(pitchValue);// 默认-5// 时间间隔15秒钟setExtentTime(flytime, viewer);Exection=functionTimeExecution(){let preIndex = marksIndex -1;if(marksIndex ===0){
preIndex = positons2.length -1;}//计算俯仰角// 当前已经过去的时间,单位sconst delTime = Cesium.JulianDate.secondsDifference(viewer.clock.currentTime, viewer.clock.startTime);const originLat = marksIndex ==0? positons2[positons2.length -1].y : positons2[marksIndex -1].y;const originLng = marksIndex ==0? positons2[positons2.length -1].x : positons2[marksIndex -1].x;const endPosition = Cesium.Cartesian3.fromDegrees((originLng +(positons2[marksIndex].x - originLng)/ flytime * delTime),(originLat +(positons2[marksIndex].y - originLat)/ flytime * delTime),
positons2[marksIndex].z
);let heading =bearing(originLat,originLng, centerPos.y, centerPos.x);// let heading = bearing(centerPos.y, centerPos.x, originLat,originLng);
heading = Cesium.Math.toRadians(heading);
viewer.scene.camera.setView({destination: endPosition,orientation:{heading: heading,pitch: pitch,}});if(Cesium.JulianDate.compare(viewer.clock.currentTime, viewer.clock.stopTime)>=0){
viewer.clock.onTick.removeEventListener(Exection);//有个转向的功能changeCameraHeading(viewer);}};
viewer.clock.onTick.addEventListener(Exection);}// 相机原地定点转向constchangeCameraHeading=(viewer)=>{// 计算两点之间的方向let nextIndex = marksIndex +1;if(marksIndex == positons2.length -1){
nextIndex =0;}const heading =bearing(positons2[marksIndex].y, positons2[marksIndex].x,centerPos.y, centerPos.x );
console.log(heading, Cesium.Math.toDegrees(viewer.camera.heading));// 相机看点的角度,如果大于0那么则是从地底往上看,所以要为负值const pitch = Cesium.Math.toRadians(pitchValue);// 给定飞行一周所需时间,比如10s, 那么每秒转动度数// 相机是始终往角度小的方向转, 先确定绘制的线路是顺时针还是逆时针_judgeDirection// 判断当前camera.heading > 两点的heading// 如果大于,则360 - camera.heading + heading, eg: 360-340+20//这部分主要解决的是相机朝哪个方向转的问题,顺时针绘制的线和逆时针绘制的线转向不同,所以有了下面这些判断,或许还有更好的办法处理let angle =0if(!isRight){// 顺时针if(Cesium.Math.toDegrees(viewer.camera.heading)> heading){
angle =((Cesium.Math.toDegrees(Cesium.Math.TWO_PI- viewer.camera.heading)+ heading)/ changeCameraTime);}else{
angle =((heading - Cesium.Math.toDegrees(viewer.camera.heading))/ changeCameraTime);}}else{if(Cesium.Math.toDegrees(viewer.camera.heading)< heading){
angle =((Cesium.Math.toDegrees(Cesium.Math.toRadians(heading)- Cesium.Math.TWO_PI)- Cesium.Math.toDegrees(viewer.camera.heading))/ changeCameraTime);}else{
angle =((heading - Cesium.Math.toDegrees(viewer.camera.heading))/ changeCameraTime);}// angle = ((heading - Cesium.Math.toDegrees(viewer.camera.heading)) / changeCameraTime);}// const angle = ((heading - Cesium.Math.toDegrees(viewer.camera.heading)) / changeCameraTime);
console.log(angle,'angle');// 时间间隔2秒钟setExtentTime(changeCameraTime, viewer);// 相机的当前headingconst initialHeading = viewer.camera.heading;Exection=functionTimeExecution(){// 当前已经过去的时间,单位sconst delTime = Cesium.JulianDate.secondsDifference(viewer.clock.currentTime, viewer.clock.startTime);// console.log(Cesium.Math.toRadians(delTime * angle), '1s转动的角度');const heading = Cesium.Math.toRadians(delTime * angle)+ initialHeading;
viewer.scene.camera.setView({orientation:{heading: heading,pitch: pitch
}});if(Cesium.JulianDate.compare(viewer.clock.currentTime, viewer.clock.stopTime)>=0){
viewer.clock.onTick.removeEventListener(Exection);
marksIndex =++marksIndex >= positons2.length ?0: marksIndex;if(marksIndex !=0){
console.log(marksIndex,'marksIndex');flyExtent(viewer);}}};
viewer.clock.onTick.addEventListener(Exection);}//计算俯仰角constbearing=(startLat, startLng, destLat, destLng)=>{
startLat =toRadians(startLat);
startLng =toRadians(startLng);
destLat =toRadians(destLat);
destLng =toRadians(destLng);const y = Math.sin(destLng - startLng)* Math.cos(destLat);const x = Math.cos(startLat)* Math.sin(destLat)- Math.sin(startLat)* Math.cos(destLat)* Math.cos(destLng - startLng);const brng = Math.atan2(y, x);const brngDgr =toDegrees(brng);return(brngDgr +360)%360;}// 角度转弧度consttoRadians=(degrees)=>{return degrees * Math.PI/180;}// 弧度转角度consttoDegrees=(radians)=>{return radians *180/ Math.PI;}
desktop 2023-04-03 11-55-18
参考大佬文章: https://blog.csdn.net/CFXXXL/article/details/125365952
版权归原作者 \'qiangwaer\' 所有, 如有侵权,请联系我们删除。