SuperMap iClient3D for WebGL 影像数据可视范围控制

在共享同一影像底图的服务场景中,如何基于用户权限体系实现差异化的数据可视范围控制?SuperMap iClient3D for WebGL提供了自定义区域影像裁剪的方法。让我们一起看看吧!

一、数据制作

对于上述视频中的地图制作,此处不做讲述,如有需要可访问:Online 开发者中心

可视化案例中提供了详细的代码、数据下载链接及数据制作过程。

二、实现思路

影像数据可视范围控制的实现思路如下图所示:

三、关键代码

遍历Geojson数据获取坐标数组关键代码如下:

javascript 复制代码
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;
}

四、示例完整代码

javascript 复制代码
<!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>
相关推荐
烛阴4 小时前
拒绝配置地狱!5 分钟搭建 Three.js + Parcel 完美开发环境
前端·webgl·three.js
WebGISer_白茶乌龙桃16 小时前
Vue3 + Mapbox 加载 SHP 转换的矢量瓦片 (Vector Tiles)
javascript·vue.js·arcgis·webgl
ThreePointsHeat5 天前
Unity WebGL打包后启动方法,部署本地服务器
unity·游戏引擎·webgl
林枫依依6 天前
电脑配置流程(WebGL项目)
webgl
冥界摄政王8 天前
CesiumJS学习第四章 替换指定3D建筑模型
3d·vue·html·webgl·js·cesium
温宇飞10 天前
高效的线性采样高斯模糊
javascript·webgl
冥界摄政王11 天前
Cesium学习第一章 安装下载 基于vue3引入Cesium项目开发
vue·vue3·html5·webgl·cesium
光影少年13 天前
三维前端需要会哪些东西
前端·webgl
nnsix13 天前
Unity WebGL jslib 通信时,传入字符串,变成数值 问题
webgl
二狗哈14 天前
Cesium快速入门34:3dTile高级样式设置
前端·javascript·算法·3d·webgl·cesium·地图可视化