SuperMap iClient3D for WebGL 影像数据可视范围控制
在共享同一影像底图的服务场景中,如何基于用户权限体系实现差异化的数据可视范围控制?SuperMap iClient3D for WebGL提供了自定义区域影像裁剪的方法。让我们一起看看吧!
一、数据制作
对于上述视频中的地图制作,此处不做讲述,如有需要可访问:Online 开发者中心
可视化案例中提供了详细的代码、数据下载链接及数据制作过程。
二、实现思路
影像数据可视范围控制的实现思路如下图所示:
三、关键代码
遍历Geojson数据获取坐标数组关键代码如下:
if (data.type === "MultiPolygon") {
// 处理 MultiPolygon 类型的数据,可能包含多个多边形
for (let i = 0; i < data.coordinates.length; i++) {
for (let j = 0; j < data.coordinates[i].length; j++) {
// 获取当前多边形的坐标数组
let positions = data.coordinates[i][j];
// 用于存储转换后的笛卡尔坐标
let superMapPositions = [];
for (let k = 0; k < positions.length; k++) {
// 将经纬度坐标转换为地理坐标对象,高度设为 0
var cartographic = SuperMap3D.Cartographic.fromDegrees(positions[k][0], positions[k][1], 0);
// 将地理坐标对象转换为笛卡尔坐标
var cartesian = SuperMap3D.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height);
superMapPositions.push(cartesian);
}
// 转换为经纬度和高度数组
let finalPositions = [];
for (let k = 0, len = superMapPositions.length; k < len; k++) {
// 将笛卡尔坐标转换为地理坐标对象
var cartographic = SuperMap3D.Cartographic.fromCartesian(superMapPositions[k]);
// 将弧度制的经度转换为角度制
var longitude = SuperMap3D.Math.toDegrees(cartographic.longitude);
// 将弧度制的纬度转换为角度制
var latitude = SuperMap3D.Math.toDegrees(cartographic.latitude);
// 获取高度值
var h = cartographic.height;
// 将经纬度和高度值依次添加到数组中
finalPositions.push(longitude);
finalPositions.push(latitude);
finalPositions.push(h);
}
// 将当前多边形的位置信息添加到 allPositions 数组中
allPositions = allPositions.concat(finalPositions);
}
}
} else if (data.type === "Polygon") {
// 处理 Polygon 类型的数据,只包含一个多边形
let positions = data.coordinates[0];
let superMapPositions = [];
for (let i = 0; i < positions.length; i++) {
var cartographic = SuperMap3D.Cartographic.fromDegrees(positions[i][0], positions[i][1], 0);
var cartesian = SuperMap3D.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height);
superMapPositions.push(cartesian);
}
// 转换为经纬度和高度数组
let finalPositions = [];
for (let i = 0, len = superMapPositions.length; i < len; i++) {
var cartographic = SuperMap3D.Cartographic.fromCartesian(superMapPositions[i]);
var longitude = SuperMap3D.Math.toDegrees(cartographic.longitude);
var latitude = SuperMap3D.Math.toDegrees(cartographic.latitude);
var h = cartographic.height;
finalPositions.push(longitude);
finalPositions.push(latitude);
finalPositions.push(h);
}
// 将当前多边形的位置信息赋值给 allPositions 数组
allPositions = finalPositions;
}
四、示例完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>自定义区域影像裁剪</title>
<link href="../../Build/SuperMap3D/Widgets/widgets.css" rel="stylesheet">
<link href="./css/pretty.css" rel="stylesheet">
<script src="./js/jquery.min.js"></script>
<script src="./js/spectrum.js"></script>
<script src="./js/config.js"></script>
<script src="./js/tooltip.js"></script>
<script type="text/javascript" src="../../Build/SuperMap3D/SuperMap3D.js"></script>
</head>
<body>
<div id="Container"></div>
<div id='loadingbar' class="spinner">
<div class="spinner-container container1">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
<div class="spinner-container container2">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
<div class="spinner-container container3">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
</div>
<div id="toolbar" class="param-container tool-bar">
<div class="param-item">
<select id="citySelector" style="width: 150px">
<option value="" selected disabled hidden>请选择所属区域</option>
<option value="guiyang_city">贵阳市</option>
<option value="anshun_city">安顺市</option>
<option value="bijie_city">毕节市</option>
<option value="liupanshui_city">六盘水市</option>
<option value="tongren_city">铜仁市</option>
<option value="zunyi_city">遵义市</option>
<option value="qiandongnan_prefecture">黔东南</option>
<option value="qiannan_prefecture">黔南</option>
<option value="qianxinan_prefecture">黔西南</option>
</select>
</div>
</div>
<script>
// 定义各城市中心点经纬度信息
const cityCenters = {
"guiyang_city": [106.713478, 26.578341],
"anshun_city": [105.934854, 26.224645],
"bijie_city": [105.291238, 27.302327],
"liupanshui_city": [104.831343, 26.590612],
"tongren_city": [109.188523, 27.704321],
"zunyi_city": [106.932211, 27.707422],
"qiandongnan_prefecture": [107.983421, 26.587345],
"qiannan_prefecture": [107.501234, 26.234567],
"qianxinan_prefecture": [104.902345, 25.098765]
};
// 页面加载完成后执行的函数,初始化 SuperMap3D 地图
function onload(SuperMap3D) {
// 通过 config.js 中的 getEngineType 函数,获取引擎类型(EngineType),用于设置启动方式
let EngineType = getEngineType();
// 创建一个 SuperMap3D 的 Viewer 实例,将其显示在 id 为 'Container' 的容器中
let viewer = new SuperMap3D.Viewer('Container', {
contextOptions: {
// 设置 WebGL 上下文类型,Webgl2 对应值为 2,WebGPU 对应值为 3
contextType: Number(EngineType),
}
});
// 当场景加载完成后,调用 init 函数进行初始化操作
viewer.scenePromise.then(function (scene) {
init(SuperMap3D, scene, viewer);
});
}
// 初始化地图场景的函数
function init(SuperMap3D, scene, viewer) {
// 设置地图的分辨率比例,根据设备的像素比进行调整
viewer.resolutionScale = window.devicePixelRatio;
$('#loadingbar').remove();
// 存储添加的影像图层
let tmpLayer = viewer.imageryLayers.addImageryProvider(
new SuperMap3D.SuperMapImageryProvider({
url: "http://localhost:8090/iserver/services/map-GuiZhou/rest/maps/%E8%B4%B5%E5%B7%9E%E7%9C%81%E5%9C%B0%E5%BD%A2%E5%9B%BE",
})
);
// 设置所加载的影像背景透明,将白色背景设为透明
tmpLayer.transparentBackColor = SuperMap3D.Color.fromCssColorString('#ffffff');
// 设置透明背景的容差,即与指定颜色相近的颜色也会被视为透明
tmpLayer.transparentBackColorTolerance = Number(0.1);
// 让地图飞到影像所在的位置,以便用户能看到影像
viewer.flyTo(tmpLayer);
// 监听城市选择框的 change 事件,当用户选择不同的城市时触发
$('#citySelector').change(function () {
// 获取用户选择的城市的值
var selectedCity = $(this).val();
if (selectedCity) {
// 根据选择的城市加载对应的 JSON 边界数据文件
$.getJSON('./data/json/' + selectedCity + '.json', function (data) {
// 用于存储所有多边形的位置信息
let allPositions = [];
if (data.type === "MultiPolygon") {
// 处理 MultiPolygon 类型的数据,可能包含多个多边形
for (let i = 0; i < data.coordinates.length; i++) {
for (let j = 0; j < data.coordinates[i].length; j++) {
// 获取当前多边形的坐标数组
let positions = data.coordinates[i][j];
// 用于存储转换后的笛卡尔坐标
let superMapPositions = [];
for (let k = 0; k < positions.length; k++) {
// 将经纬度坐标转换为地理坐标对象,高度设为 0
var cartographic = SuperMap3D.Cartographic.fromDegrees(positions[k][0], positions[k][1], 0);
// 将地理坐标对象转换为笛卡尔坐标
var cartesian = SuperMap3D.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height);
superMapPositions.push(cartesian);
}
// 转换为经纬度和高度数组
let finalPositions = [];
for (let k = 0, len = superMapPositions.length; k < len; k++) {
// 将笛卡尔坐标转换为地理坐标对象
var cartographic = SuperMap3D.Cartographic.fromCartesian(superMapPositions[k]);
// 将弧度制的经度转换为角度制
var longitude = SuperMap3D.Math.toDegrees(cartographic.longitude);
// 将弧度制的纬度转换为角度制
var latitude = SuperMap3D.Math.toDegrees(cartographic.latitude);
// 获取高度值
var h = cartographic.height;
// 将经纬度和高度值依次添加到数组中
finalPositions.push(longitude);
finalPositions.push(latitude);
finalPositions.push(h);
}
// 将当前多边形的位置信息添加到 allPositions 数组中
allPositions = allPositions.concat(finalPositions);
}
}
} else if (data.type === "Polygon") {
// 处理 Polygon 类型的数据,只包含一个多边形
let positions = data.coordinates[0];
let superMapPositions = [];
for (let i = 0; i < positions.length; i++) {
var cartographic = SuperMap3D.Cartographic.fromDegrees(positions[i][0], positions[i][1], 0);
var cartesian = SuperMap3D.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height);
superMapPositions.push(cartesian);
}
// 转换为经纬度和高度数组
let finalPositions = [];
for (let i = 0, len = superMapPositions.length; i < len; i++) {
var cartographic = SuperMap3D.Cartographic.fromCartesian(superMapPositions[i]);
var longitude = SuperMap3D.Math.toDegrees(cartographic.longitude);
var latitude = SuperMap3D.Math.toDegrees(cartographic.latitude);
var h = cartographic.height;
finalPositions.push(longitude);
finalPositions.push(latitude);
finalPositions.push(h);
}
// 将当前多边形的位置信息赋值给 allPositions 数组
allPositions = finalPositions;
}
// 移除之前的裁剪区域,避免重叠
viewer.scene.globe.removeImageryClipRegion("clip", [tmpLayer]);
// 添加新的裁剪区域,根据选择的城市边界对影像进行裁剪
viewer.scene.globe.addImageryClipRegions({
position: allPositions,
layers: [tmpLayer],
name: "clip"
});
// 获取所选城市的中心点坐标
const [lon, lat] = cityCenters[selectedCity];
// 创建地理坐标对象
const center = SuperMap3D.Cartographic.fromDegrees(lon, lat);
// 创建笛卡尔坐标对象
const centerCartesian = SuperMap3D.Cartesian3.fromRadians(center.longitude, center.latitude, 530000);
// 让地图飞到城市中心点
viewer.camera.flyTo({
destination: centerCartesian,
duration: 3 // 飞行时间,单位为秒
});
});
}
});
}
// 检查 SuperMap3D 是否已经定义,如果已经定义则调用 onload 函数进行初始化
if (typeof SuperMap3D!== 'undefined') {
onload(SuperMap3D);
}
</script>
</body>
</html>