SuperMap iClient3D for WebGL 如何限制相机高度及范围

 作者:zhouyp

目录

一、前言

二、关键代码

三、完整示例代码


一、前言

在iClient3D for WebGL中限制相机高度及范围可以提高用户体验,防止用户缩放到不合适的高度或超出预定的地理范围,一起来看看如何实现吧!

效果
图1、示例效果

二、关键代码

监听scene.preRender事件,该事件将会在每帧渲染之前触发,事件回调中我们获取到当前帧的相机位置,当超出高度和范围限制条件时将相机位置修改为限制条件阈值。详情代码如需:

        let minHeight = 400, maxHeight = 15000;
        let west = 13.000, south = 47.785, east = 13.105, north = 47.858;

        viewer.scene.preRender.addEventListener(function () {
            updateCameraPositionWithConstrants(
                viewer.camera,
                minHeight,
                maxHeight,
                west,
                east,
                north,
                south);
        });

        // 获取约束条件下相机位置
        function updateCameraPositionWithConstrants(currentCamera, minHeight, maxHeight, west, east, north, south) {
            //获取 当前相机经度纬度高度
            let cartographic = SuperMap3D.Cartographic.fromCartesian(currentCamera.position);
            let longitude = SuperMap3D.Math.toDegrees(cartographic.longitude);
            let latitude = SuperMap3D.Math.toDegrees(cartographic.latitude);
            let height = cartographic.height;
            let trigger = false;

            // 判断相机位置是否触发高度约束,若触发将其值修改为高度约束阈值
            if (height < minHeight) {
                height = minHeight;
                trigger = true;
            }
            if (height > maxHeight) {
                height = maxHeight;
                trigger = true;
            }

            // 判断相机位置是否触发范围约束,若触发将其值修改为范围约束阈值
            if (longitude < west) {
                longitude = Math.max(longitude, west);
                trigger = true;
            }
            if (longitude > east) {
                longitude = Math.min(longitude, east);
                trigger = true;
            }
            if (latitude > north) {
                latitude = Math.min(latitude, north);
                trigger = true;
            }
            if (latitude < south) {
                latitude = Math.max(latitude, south);
                trigger = true;
            }

            if (trigger) {
                currentCamera.position = SuperMap3D.Cartesian3.fromDegrees(longitude, latitude, height);;
            }
        }

三、完整示例代码

注:复制后放入iClient3D for WebGL 范例沙盒中可以直接运行

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta name="viewport"
        content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    <title>限制相机高度及范围</title>
    <link href="../../Build/SuperMap3D/Widgets/widgets.css" rel="stylesheet">
    <link href="./css/pretty.css" rel="stylesheet">
    <link href="./css/style.css" rel="stylesheet">
    <link href="./style/cloudAndSky.css" rel="stylesheet">
    <script type="text/javascript" src="./js/jquery.min.js"></script>
    <script src="./js/tooltip.js"></script>
    <script src="./js/spectrum.js"></script>
    <script src="./js/config.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="titleBox">
            <div class="titl">限制相机高度及范围</div>
        </div>
        <div class="param-item inputBox showCloud">
            <label class="lable">最大高度</label>
            <input id="maxVisual" type="number" value="15000" style="text-align: center">
        </div>
        <div class="param-item inputBox showCloud">
            <label class="lable">最小高度</label>
            <input id="minVisual" type="number" value="400" style="text-align: center">
        </div>
        <div class="param-item inputBox showCloud">
            <label class="lable">限制范围</label>
            <label class="lable">
                <div style="height: 1px;margin-top: 16px;background: red;
            "></div>
            </label>
        </div>
        <div class="param-item inputBox showCloud">
            <label class="lable">相机高度(米)</label>
            <label class="lable" id="currentH"></label>
        </div>
        <div class="param-item inputBox showCloud">
            <label class="lable">相机经度(度)</label>
            <label class="lable" id="currentLon"></label>
        </div>
        <div class="param-item inputBox showCloud">
            <label class="lable">相机纬度(度)</label>
            <label class="lable" id="currentLat"></label>
        </div>

    </div>
    <script type="text/javascript">
        function onload(SuperMap3D) {
            let viewer = new SuperMap3D.Viewer('Container', {
                contextOptions: {
                    contextType: Number(2), // Webgl2:2 ; WebGPU:3
                }
            });
            viewer.scenePromise.then(function (scene) {
                scene.globe.depthTestAgainstTerrain = false;
                init(SuperMap3D, scene, viewer);
            });
        }

        function init(SuperMap3D, scene, viewer) {
            viewer.resolutionScale = window.devicePixelRatio;
            let widget = viewer.Widget;
            try {
                // 打开三维场景
                let promise = scene.open(URL_CONFIG.SCENE_SRSB);
                SuperMap3D.when(promise, function (layers) {
                    layers.forEach(layer => {
                        layer.selectEnabled = false;
                        let style = new SuperMap3D.Style3D();
                        style.bottomAltitude = -58;
                        layer.style3D = style;
                        layer.setLodRangeScale(0.1)
                        layer.refresh();
                    })

                    // 获取界面高度范围
                    let minHeight = parseFloat($("#minVisual").val());
                    let maxHeight = parseFloat($("#maxVisual").val());
                    // 监听界面高度范围变化
                    $("#minVisual").on('input', function () {
                        minHeight = parseFloat($("#minVisual").val());
                        maxHeight = parseFloat($("#maxVisual").val());
                        if (minHeight > maxHeight) {
                            minHeight = maxHeight
                            $("#minVisual").val(minHeight)
                        }
                    });
                    $("#maxVisual").on('input', function () {
                        minHeight = parseFloat($("#minVisual").val());
                        maxHeight = parseFloat($("#maxVisual").val());
                        if (maxHeight < minHeight) {
                            maxHeight = minHeight
                            $("#maxVisual").val(maxHeight)
                        }
                    });

                    // 约束相机移动范围
                    let west = 13.000, south = 47.785, east = 13.105, north = 47.858;
                    let rectangle = SuperMap3D.Rectangle.fromDegrees(west, south, east, north);
                    viewer.camera.setView({
                        destination: rectangle
                    });
                    viewer.entities.add({
                        rectangle: {
                            coordinates: rectangle,
                            fill: false,
                            outline: true,
                            outlineColor: SuperMap3D.Color.RED,
                            outlineWidth: 10,
                        },
                    });

                    viewer.scene.preRender.addEventListener(function () {
                        updateCameraPositionWithConstrants(
                            viewer.camera,
                            minHeight,
                            maxHeight,
                            west,
                            east,
                            north,
                            south);
                    });

                    // 获取约束条件下相机位置
                    function updateCameraPositionWithConstrants(currentCamera, minHeight, maxHeight, west, east, north, south) {
                        //获取 当前相机经度纬度高度
                        let cartographic = SuperMap3D.Cartographic.fromCartesian(currentCamera.position);
                        let longitude = SuperMap3D.Math.toDegrees(cartographic.longitude);
                        let latitude = SuperMap3D.Math.toDegrees(cartographic.latitude);
                        let height = cartographic.height;
                        let trigger = false;

                        // 判断相机位置是否触发高度约束,若触发将其值修改为高度约束阈值
                        if (height < minHeight) {
                            height = minHeight;
                            trigger = true;
                        }
                        if (height > maxHeight) {
                            height = maxHeight;
                            trigger = true;
                        }
                        
                        // 判断相机位置是否触发范围约束,若触发将其值修改为范围约束阈值
                        if (longitude < west) {
                            longitude = Math.max(longitude, west);
                            trigger = true;
                        }
                        if (longitude > east) {
                            longitude = Math.min(longitude, east);
                            trigger = true;
                        }
                        if (latitude > north) {
                            latitude = Math.min(latitude, north);
                            trigger = true;
                        }
                        if (latitude < south) {
                            latitude = Math.max(latitude, south);
                            trigger = true;
                        }

                        if (trigger) {
                            currentCamera.position = SuperMap3D.Cartesian3.fromDegrees(longitude, latitude, height);;
                        }
                    }

                    // 相机位置发生变化时同步状态到界面
                    viewer.scene.camera.changed.addEventListener(function () {
                        let cartographic = SuperMap3D.Cartographic.fromCartesian(viewer.camera.position);
                        let height = cartographic.height;
                        let longitude = SuperMap3D.Math.toDegrees(cartographic.longitude);
                        let latitude = SuperMap3D.Math.toDegrees(cartographic.latitude);
                        $("#currentH").text(Math.round(height));
                        $("#currentLon").text(longitude.toFixed(6));
                        $("#currentLat").text(latitude.toFixed(7));
                    })
                }, function () {
                    let title = '加载SCP失败,请检查网络连接状态或者url地址是否正确?';
                    widget.showErrorPanel(title, undefined, e);
                });
            }
            catch (e) {
                if (widget._showRenderLoopErrors) {
                    let title = '渲染时发生错误,已停止渲染。';
                    widget.showErrorPanel(title, undefined, e);
                }
            }

            $("#loadingbar").remove();
            $("#toolbar").show();
        }
        if (typeof SuperMap3D !== 'undefined') {
            window.startupCalled = true;
            onload(SuperMap3D);
        }
    </script>
</body>

</html>

### 回答1: SuperMap iClient 3D for WebGL 是一款基于 WebGL 技术的三维地图开发工具,主要用于构建具有三维效果的地图应用程序。该工具提供了丰富的 API 接口和示例代码,可以帮助开发者快速上手,实现各种三维地图功能,如地形展示、建筑物模型、动态效果等。同时,SuperMap iClient 3D for WebGL 还支持多种数据格式,包括 SuperMap iServer 数据、OGC 标准数据、KML、GeoJSON 等,可以满足不同应用场景的需求。 ### 回答2: SuperMap iClient3D for WebGL是一个基于WebGL技术的三维地图开发框架。它提供了一系列的API和工具,使开发人员能够更加轻松地构建出高质量的三维地图应用。下面,我将从以下几个方面介绍SuperMap iClient3D for WebGL教程。 一、环境配置 SuperMap iClient3D for WebGL的开发需要先配置开发环境,包括安装Node.js、下载安装SuperMap iServer、下载安装SuperMap iClient3D资源包、创建Web应用程序。 二、基本概念 在学习SuperMap iClient3D for WebGL之前,需要了解一些基本概念。这些概念包括:场景(Scene)、层(Layer)、覆盖物(Overlay)等。在使用SuperMap iClient3D for WebGL时需要理解这些概念。 三、API使用 SuperMap iClient3D for WebGL提供了众多的API,使用这些API能够快速构建出一个三维地图应用。这些API包括:场景相关的API,如创建场景、设置场景属性等;层相关的API,如加载图层数据、隐藏、显示图层等;覆盖物相关的API,如创建点、线、面等覆盖物。 四、进阶应用 在掌握SuperMap iClient3D for WebGL的基础之后,可以通过进阶应用来进一步加深对这个框架的理解。进阶应用包括地球的三维测量、地球的动态效果、地球的热点区域等。 总之,SuperMap iClient3D for WebGL是一个非常实用的三维地图开发框架。通过学习其教程,开发人员可以更加方便、快速地构建出高质量的三维地图应用。 ### 回答3: SuperMap iClient 3D for WebGL是一款基于WebGL技术的开源GIS JavaScript库,用于构建高效、功能强大的3D GIS应用程序。这个库支持在Web浏览器里实现高质量的三维可视化效果,包括三维地形、建筑物、模型、标签等。现在,我来为你们讲解一下关于SuperMap iClient 3D for WebGL的教程。 一、前置知识 在接触SuperMap iClient 3D for WebGL之前,建议你先学习基本的WebGL知识和JavaScript语言,也应该具备计算机图形学基础和3D模型制作知识。 二、环境配置 在使用SuperMap iClient 3D for WebGL前,我们需要进行环境配置,在编写和运行项目时可以根据需要安装一系列依赖项,例如Node.js、npm包管理器、Gulp自动化工具、webpack工具和TypeScript编译器等。 三、基本使用 SuperMap iClient 3D for WebGL提供了丰富的API以实现3D可视化应用程序的开发,其中包括地图、图层、标注、工具、渲染等方面。同时,它还提供了多种数据格式的支持,如XYZ、OGC、JSON、KML、GML等。此外,SuperMap iClient 3D for WebGL还支持多种操作和交互方式,如平移、旋转、缩放、选取、编辑等,让用户可以更加自由地探索和编辑地图数据。 四、示例应用 SuperMap iClient 3D for WebGL提供了一系列的示例应用程序,可以帮助用户更好的理解其使用方法和特点,其中包括一些经典的三维场景展示和实时数据可视化等。例如,用户可以体验到城市三维建模、天气预报、热力图、空气质量监控等实用的功能。此外,SuperMap iClient 3D for WebGL也提供了一些模板和组件,供用户快速搭建自己的3D GIS应用程序。 总之,SuperMap iClient 3D for WebGL是一款非常优秀的基于WebGL技术的GIS JavaScript库,具有开源、高效、功能强大、易用等特点,可以为用户提供丰富多彩的三维GIS应用程序。当然,在使用前,建议用户先了解基本的WebGL和JavaScript知识,同时还需配置好开发环境。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值