cesium获取当前窗口和相机高度
在项目开发中,有用到2/3维地图缩放,获取当前视口,绘制当前视口区域内容的功能首先我们先需要监听用户的缩放事件,然后在高度和视口内容
cesium监听缩放事件
方法1:camera.changed
优点:响应式,相机发生变化时触发
缺点:不灵敏,有时候缩放幅度小不触发,缩小也不触发
viewer.camera.changed.addEventListener(() => {// 获取相机高度let height= viewer.camera.positionCartographic.height;})
方法2:鼠标滚轮
优点:监听滚轮滚动时触发,响应灵敏
缺点:不用滚轮缩放无法监听到
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)handler.setInputAction((wheelment) => {// 获取相机高度let height= viewer.camera.positionCartographic.height;}, Cesium.ScreenSpaceEventType.WHEEL)
方法3:时间监听clock.onTick
优点:根据cesium内置时钟每个时刻都执行
缺点:无论有无缩放都会触发
viewer.clock.onTick.addEventListene(() => {// 获取相机高度let height= viewer.camera.positionCartographic.height;})
获取相机高度和位置姿态
获取相机高度
// 获取相机高度
let height= viewer.camera.positionCartographic.height;
获取相机位置姿态
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)handler.setInputAction((ev) => {// 获取当前相机xyz坐标let pos = viewer.scene.camera.positionconsole.log(pos)//将笛卡尔坐标转化为经纬度坐标var cartographic = Cesium.Cartographic.fromCartesian(pos);var lon = Cesium.Math.toDegrees(cartographic.longitude);var lat = Cesium.Math.toDegrees(cartographic.latitude);var alt = cartographic.height;console.log({lon, lat, alt })// 获取相机姿态参数var h = viewer.scene.camera.heading;var p = viewer.scene.camera.pitch;var r = viewer.scene.camera.roll;console.log({h, p, r}) }, Cesium.ScreenSpaceEventType.WHEEL)
获取窗口经纬度范围
获取视口经纬度范围有两种方式:
方法1:根据窗口左上角和右下角的点计算整个视口的经纬度范围,如果左上角有右下角不在地图是就无法得到结果,适用于2维
方法2:使用viewer.camera.computeViewRectangle() 方法获取可视矩形窗口经纬度范围
const getViewExtend = ()=> {let params = {};let extend = viewer.camera.computeViewRectangle();// 通过窗口左上角和右下角坐标获取经纬度范围if (typeof extend === "undefined") {//2D下会可能拾取不到坐标,extend返回undefined,所以做以下转换let canvas = viewer.scene.canvas;let upperLeft = new Cesium.Cartesian2(0, 0);//canvas左上角坐标转2d坐标let lowerRight = new Cesium.Cartesian2(canvas.clientWidth,canvas.clientHeight);//canvas右下角坐标转2d坐标let ellipsoid = viewer.scene.globe.ellipsoid;let upperLeft3 = viewer.camera.pickEllipsoid(upperLeft,ellipsoid);//2D转3D世界坐标let lowerRight3 = viewer.camera.pickEllipsoid(lowerRight,ellipsoid);//2D转3D世界坐标let upperLeftCartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(upperLeft3);//3D世界坐标转弧度let lowerRightCartographic= viewer.scene.globe.ellipsoid.cartesianToCartographic(lowerRight3);//3D世界坐标转弧度let minx = Cesium.Math.toDegrees(upperLeftCartographic.longitude);//弧度转经纬度let maxx = Cesium.Math.toDegrees(lowerRightCartographic.longitude);//弧度转经纬度let miny = Cesium.Math.toDegrees(lowerRightCartographic.latitude);//弧度转经纬度let maxy = Cesium.Math.toDegrees(upperLeftCartographic.latitude);//弧度转经纬度console.log("经度:" + minx + "----" + maxx);console.log("纬度:" + miny + "----" + maxy);params.minx = minx;params.maxx = maxx;params.miny = miny;params.maxy = maxy;} else {//3D获取方式 通过computeViewRectangle 获取可视区域矩形范围params.maxx = Cesium.Math.toDegrees(extend.east);params.maxy = Cesium.Math.toDegrees(extend.north);params.minx = Cesium.Math.toDegrees(extend.west);params.miny = Cesium.Math.toDegrees(extend.south);}return params;//返回屏幕所在经纬度范围// return[params.maxx, params.maxy, params.maxx, params.miny, params.minx, params.miny, params.minx, params.maxy,params.maxx, params.maxy]
}
实现获取当前窗口范围的代码
// 获取相机高度
const getCameraH = () => {const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)handler.setInputAction((wheelment) => {let height= viewer.camera.positionCartographic.height;if(height<3516495) {let params = getViewExtend()let arr = [params.maxx, params.maxy, params.maxx, params.miny, params.minx, params.miny, params.minx, params.maxy,params.maxx, params.maxy]// 绘制范围createPolygon(arr, "id-123", "范围")}}, Cesium.ScreenSpaceEventType.WHEEL)}// 获取窗口范围
const getViewExtend = ()=> {let params = {};let extend = viewer.camera.computeViewRectangle();// 通过窗口左上角和右下角坐标获取经纬度范围if (typeof extend === "undefined") {//2D下会可能拾取不到坐标,extend返回undefined,所以做以下转换let canvas = viewer.scene.canvas;let upperLeft = new Cesium.Cartesian2(0, 0);//canvas左上角坐标转2d坐标let lowerRight = new Cesium.Cartesian2(canvas.clientWidth,canvas.clientHeight);//canvas右下角坐标转2d坐标let ellipsoid = viewer.scene.globe.ellipsoid;let upperLeft3 = viewer.camera.pickEllipsoid(upperLeft,ellipsoid);//2D转3D世界坐标let lowerRight3 = viewer.camera.pickEllipsoid(lowerRight,ellipsoid);//2D转3D世界坐标let upperLeftCartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(upperLeft3);//3D世界坐标转弧度let lowerRightCartographic= viewer.scene.globe.ellipsoid.cartesianToCartographic(lowerRight3);//3D世界坐标转弧度let minx = Cesium.Math.toDegrees(upperLeftCartographic.longitude);//弧度转经纬度let maxx = Cesium.Math.toDegrees(lowerRightCartographic.longitude);//弧度转经纬度let miny = Cesium.Math.toDegrees(lowerRightCartographic.latitude);//弧度转经纬度let maxy = Cesium.Math.toDegrees(upperLeftCartographic.latitude);//弧度转经纬度console.log("经度:" + minx + "----" + maxx);console.log("纬度:" + miny + "----" + maxy);params.minx = minx;params.maxx = maxx;params.miny = miny;params.maxy = maxy;} else {//3D获取方式 通过computeViewRectangle 获取可视区域矩形范围params.maxx = Cesium.Math.toDegrees(extend.east);params.maxy = Cesium.Math.toDegrees(extend.north);params.minx = Cesium.Math.toDegrees(extend.west);params.miny = Cesium.Math.toDegrees(extend.south);}return params;//返回屏幕所在经纬度范围// return[params.maxx, params.maxy, params.maxx, params.miny, params.minx, params.miny, params.minx, params.maxy,params.maxx, params.maxy]
}// 绘制范围
const createPolygon =(lonlat, id, name)=> {var ploy = Cesium.Cartesian3.fromDegreesArray(lonlat);var polyCenter = Cesium.BoundingSphere.fromPoints(ploy).center;if(viewer.entities.getById(id)){viewer.entities.remove(viewer.entities.getById(id))}viewer.entities.add({id: id,position: polyCenter,polygon: {hierarchy: Cesium.Cartesian3.fromDegreesArray(lonlat),clampToGround: false,show: true,fill: true,material: Cesium.Color.RED.withAlpha(0.5),width: 3,outlineColor: Cesium.Color.BLACK,outlineWidth: 2,outline: true,},label: {fillColor: Cesium.Color.fromCssColorString("#ffff00"),font: "12pt SiYuan",outlineColor: new Cesium.Color(0, 0, 0, 1),outlineWidth: 2,show: true,style: Cesium.LabelStyle.FILL_AND_OUTLINE,text: name,},});}
三维效果:
二维效果: