项目中有限制用户地图浏览范围的需求,经过研究以及查找相关资料,得出了一个可行方法:1、限制用户浏览视角的高度范围,然后实时监测镜头的范围,最后用实时镜头范围与限制范围的经纬度进行对比,超出就跳回初始视角,如下:
限制镜头的高度使用cesium自带api就可以直接实现,如下:
viewer.scene.screenSpaceCameraController.maximumZoomDistance =200000;
viewer.scene.screenSpaceCameraController.minimumZoomDistance = 10;
想要实时监测镜头范围,通过查找相关的文章学习到到了两个cesium的方法:
//实时监测方法,该方法会不停的调用,频率相当高
viewer.scene.preRender.addEventListener();
//计算镜头范围方法,该方法会计算当前镜头地理坐标(弧度)范围并返回west,east,north,south 4个范围参数
viewer.camera.computeViewRectangle();
将两者组合就可以实时监测镜头地理坐标(弧度)范围了:
viewer.scene.preRender.addEventListener(function() {
let rectangle = viewer.camera.computeViewRectangle();
//rectangle 为当前镜头的实时范围
}
通过查找相关资料找到了地理坐标(弧度)转经纬度坐标的方法,如下:
// 将弧度转为经纬度,west为左(西)侧边界的经度,以下类推
let west =rectangle.west / Math.PI * 180;
let north = rectangle.north / Math.PI * 180;
let east = rectangle.east / Math.PI * 180;
let south = rectangle.south / Math.PI * 180;
设置可浏览的经纬度范围:
//按需求设置可浏览的经纬度边界
let Range = {west:100.111111,north:25.11111,east:105.11111,south:28.111111};
判断超出跳回:
//如果视角超出设置经纬度范围则跳转视角
if(west < Range.west || north < Range.north || east > Range.east || south > Range.south){
console.log("跳转视角");
viewer.scene.camera.setView({
destination: new Cesium.Cartesian3(-1264160.070654434, 5665789.912013389, 2654915.919083717),
orientation: {
heading: 0.16290833989833153,
pitch: -0.43768116366765275,
roll: 6.283129299301802
}
});
}
//可以选择flyto方法,飞行更流畅
//限制地图浏览范围
//限制镜头高度
viewer.scene.screenSpaceCameraController.maximumZoomDistance =200000;
viewer.scene.screenSpaceCameraController.minimumZoomDistance = 10;
//实时监测镜头范围(该方法会一直调用)
viewer.scene.preRender.addEventListener(function() {
//计算镜头范围方法,该方法会计算当前镜头地理坐标(弧度)范围并返回west,east,north,south 4个范围参数
let rectangle = viewer.camera.computeViewRectangle();
// console.log(rectangle,'rectangle');
//设置可浏览经纬度范围
let Range = {west:100.111111,north:25.11111,east:105.11111,south:28.111111};
//地理坐标(弧度)转经纬度坐标
// 弧度转为经纬度,west为左(西)侧边界的经度,以下类推
let west =rectangle.west / Math.PI * 180;
let north = rectangle.north / Math.PI * 180;
let east = rectangle.east / Math.PI * 180;
let south = rectangle.south / Math.PI * 180;
//如果视角超出设置范围则跳转视角
if(west < Range.west || north < Range.north || east > Range.east || south > Range.south){
//console.log("跳转视角");
viewer.scene.camera.setView({
destination: new Cesium.Cartesian3(-1264160.070654434, 5665789.912013389, 2654915.919083717),
orientation: {
heading: 0.16290833989833153,
pitch: -0.43768116366765275,
roll: 6.283129299301802
}
});
}
)};
//可以选择flyto方法,飞行更流畅
该方式实现浏览范围限制,有两个弊端:
1、preRender.addEventListener()方法会一直调用,频率很高,不利于前端性能优化,尤其是加载大型地图后,本来就卡顿的界面,可能会更加卡顿,且如果初始范围小于设置的浏览范围,就会一直触发视角跳转,导致死循环,无法操作。
2、拉到地图边界跳转视角,不利于用户体验,到范围边界后禁止往更外面拖动与放大,才是更优秀的方法,但笔者未找到相关实现方式,有知道的大佬可以评论区留言。
更好的实现方式
因以上两个弊端,因此笔者项目中弃用了此方法,改为按需加载相应图层,这样既可减少图层加载数量,也不会有以上两个弊端,更利于前端性能优化。建议大家最好也使用此种方式实现范围限制。
参考大佬传送门:
https://www.cnblogs.com/xt112233/p/14044460.html
https://blog.csdn.net/u011495292/article/details/81207144
https://blog.csdn.net/pyx6119822/article/details/81208151
https://blog.csdn.net/zhengshaofeng1/article/details/113613138
https://blog.csdn.net/qq_42036616/article/details/90140636