cesium workshop 1.51

此代码是我自己阅读cesium workshop 1.51时学习用的,经测试可用,直接上代码:

<!DOCTYPE html>
<html lang="en">
    <head>
        <!-- Use correct character set. -->
        <meta charset="utf-8">
        <!-- Tell IE to use the latest, best version. -->
        <meta http-equiv="X-UA-Compatible" content="IE=Edge">
        <!-- Make the app on mobile take up the full browser screen and disable user scaling. -->
        <meta name="viewport"
            content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
        <title>workshop2</title>
        <!-- The Cesium library. -->
        <script src="../ThirdParty/Cesium/Cesium.js"></script>
        <!-- Style our app. -->
        <link rel="stylesheet" href="../index.css" media="screen">
    </head>
    <body>
        <div id="cesiumContainer"></div>
        <!-- Some input elements for our app. -->
        <div class="backdrop" id="menu">
            <h2>Sample NYC Geocaches</h2>
            <span><strong>Camera Mode</strong></span>
            <div class="nowrap">
                <input id="freeMode" name="source" type="radio" checked/>
                <label for="freeMode">Free</label>
            </div>
            <div class="nowrap">
                <input id="droneMode" name="source" type="radio"/>
                <label for="droneMode">Drone View</label>
            </div>
            <br>
            <span><strong>3d Tile Styling</strong></span>
            <div class="nowrap">
                <select id="tileStyle">
                    <option value="none">None</option>
                    <option value="height">Height</option>
                    <option value="transparent">Transparent</option>
                </select>
            </div>
            <br>
            <span><strong>Display Options</strong></span>
            <div class="nowrap">
                <input id="shadows" type="checkbox"/>
                <label for="shadows">Shadows</label>
            </div>
            <div class="nowrap">
                <input id="neighborhoods" type="checkbox" checked/>
                <label for="neighborhoods">Neighborhoods</label>
            </div>
            <br>
        </div>
        <div id="loadingIndicator" class="cover">
            <div id="loadingIcon" class="loadingIndicator"></div>
        </div>

        <!--业务代码。-->
        <script>
            // Cesium 离子 默认密钥。
            Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiMGRjM2QxYi04ODM2LTQzMDEtOGJmOS1mNDlkY2Q2NjE4MjciLCJpZCI6MjU5LCJpYXQiOjE1MjU5NjYyMDd9.xW9loNLo68KE3ReAHd-Lp73M8qJKhI9vA0wYL-qJX_I';
            // var viewer = new Cesium.Viewer('cesiumContainer');
            // 创建带参数视图。
            let viewer = new Cesium.Viewer('cesiumContainer', {
                scene3DOnly: true,  // 只看3D场景。(场景模式选择器3D, 2D and Columbus View (CV))
                selectionIndicator: false,  // 作用未知。
                baseLayerPicker: false  //  基层拾取器。
            });


            // 设置时钟和时间线。
            viewer.clock.shouldAnimate = true; // 在视图开始时,播放动画。
            // 时间线开始时间(UTC). 2017-07-11 16:00:00 UTC.
            viewer.clock.startTime = Cesium.JulianDate.fromIso8601("2017-07-11T16:00:00Z");
            // 时间线终止时间(UTC)。
            viewer.clock.stopTime = Cesium.JulianDate.fromIso8601("2017-07-11T16:20:00Z");
            // 时钟当前时间。
            viewer.clock.currentTime = Cesium.JulianDate.fromIso8601("2017-07-11T16:00:00Z");
            // 2倍速播放动画。
            viewer.clock.multiplier = 2;
            // 滴答计算模式(感觉要和上一个参数联合使用)
            viewer.clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER;
            // 末端循环,就是时间走到最后,从头再来,循环往复。
            viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
            // 设置时间线的可见范围。
            viewer.timeline.zoomTo(viewer.clock.startTime, viewer.clock.stopTime);


            // 移除默认基层。
            viewer.imageryLayers.remove(viewer.imageryLayers.get(0));
            // 添加Sentinel-2 影像。
            viewer.imageryLayers.addImageryProvider(new Cesium.IonImageryProvider({ assetId : 3954 }));

            // 加载 Cesium 世界地形。
            viewer.terrainProvider = Cesium.createWorldTerrain({
                requestWaterMask : true, // 水效应所需
                requestVertexNormals : true // 地形照明所需。
            });
            // 启用深度测试,使地形后面的东西消失。
            viewer.scene.globe.depthTestAgainstTerrain = true;
            // 启用 基于日月位置的 照明。(可以知道当前哪是白天,哪是黑夜。)
            // viewer.scene.globe.enableLighting = true;


            // 以下要创建初始视图
            // 初始化位置。
            let initialPosition = new Cesium.Cartesian3.fromDegrees(-73.998114468289017509, 40.674512895646692812, 2631.082799425431);
            // 初始化朝向。
            let initialOrientation = new Cesium.HeadingPitchRoll.fromDegrees(7.1077496389876024807, -31.987223091598949054, 0.025883251314954971306);
            let homeCameraView = {
                destination : initialPosition,  // 目的地。
                orientation : {
                    heading : initialOrientation.heading,  // 水平朝向
                    pitch : initialOrientation.pitch,  // 俯仰角。
                    roll : initialOrientation.roll  // 左右旋转。
                }  // 朝向定位。
            };
            // 设置初始视图
            viewer.scene.camera.setView(homeCameraView);


            // 以下要重写默认的主视图,及飞到主视图之前的过渡效果。
            // 添加一些相机飞行动画选项,主要用于flyTo函数的飞行效果。
            homeCameraView.duration = 2.0;  // 飞行时间2秒。
            homeCameraView.maximumHeight = 2000;  // 飞行最大高度。
            homeCameraView.pitchAdjustHeight = 2000;  // 飞行时,俯仰调整高度
            homeCameraView.endTransform = Cesium.Matrix4.IDENTITY;
            // 重写默认的主视图。
            viewer.homeButton.viewModel.command.beforeExecute.addEventListener(function (e) {
                // 取消默认的主视图。
                e.cancel = true;
                // 显示新的主视图。
                viewer.scene.camera.flyTo(homeCameraView);
            });


            // 以下要从kml文件加载geocache兴趣点到视图。
            // 文件加载选项。
            let kmlOptions = {
                camera : viewer.scene.camera,
                canvas : viewer.scene.canvas,
                clampToGround : true
            };
            // 加载。
            // Data from : http://catalog.opendata.city/dataset/pediacities-nyc-neighborhoods/resource/91778048-3c58-449c-a3f9-365ed203e914
            let geocachePromise = Cesium.KmlDataSource.load('../Source/SampleData/sampleGeocacheLocations.kml', kmlOptions);
            // 解析。
            geocachePromise.then(function(dataSource){
                // 将新数据作为实体添加到视图中。
                viewer.dataSources.add(dataSource);
                // 获取实体数组,遍历每个实体,设置其样式。
                let geocacheEntities = dataSource.entities.values;
                for (let i=0; i<geocacheEntities.length;i++){
                    let entity = geocacheEntities[i];
                    if (Cesium.defined(entity.billboard)){
                        // 调整垂直原点,使引脚固定在地形上。
                        entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
                        // 禁用标签以减少杂乱
                        entity.label = undefined;
                        // 生成标签
                        // entity.label = {
                        //     text : entity.name,
                        //     showBackground : true,
                        //     scale : 0.6,
                        //     horizontalOrigin : Cesium.HorizontalOrigin.LEFT,
                        //     verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
                        //     distanceDisplayCondition : new Cesium.DistanceDisplayCondition(10.0, 8000.0),
                        //     // disableDepthTestDistance : 100.0 // 可以是标签随时可见,不被实体遮挡。
                        // };
                        // 添加距离显示条件。(广告牌在10 - 2万米距离内显示。)
                        entity.billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(10.0, 20000.0);

                        // 以下要设置每个实体的 信息弹窗,弹窗标题是实体名称,内容只有经纬度。
                        // 获取此时此刻的实体位置。getValue(time, result),Cesium.JulianDate.now()创建表示当前系统时间的新实例。
                        let cartographicPosition = Cesium.Cartographic.fromCartesian(entity.position.getValue(Cesium.JulianDate.now()));
                        // console.log("Cesium.JulianDate.now():", Cesium.JulianDate.now());
                        // JulianDate {dayNumber: 2458458, secondsOfDay: 69468.57}
                        let longitude = Cesium.Math.toDegrees(cartographicPosition.longitude);
                        let latitude = Cesium.Math.toDegrees(cartographicPosition.latitude);
                        // 修改描述。
                        let description = '<table class="cesium-infoBox-defaultTable cesium-infoBox-defaultTable-lighter"><tbody>' +
                            '<tr><th>' + "Longitude" + '</th><td>' + longitude.toFixed(5) + '</td></tr>' +
                            '<tr><th>' + "Latitude" + '</th><td>' + latitude.toFixed(5) + '</td></tr>' +
                            '</tbody></table>';
                        entity.description = description;
                    }
                }
            });


            // 以下要加载geojson类型的文件,用颜色分类不同的地块。
            // 加载选项。
            let geojsonOptions = {
                clampToGround : true  // 紧贴地面。
            };
            // 从Geojson文件加载邻域边界
            let neighborhoodsPromise = Cesium.GeoJsonDataSource.load('../Source/SampleData/sampleNeighborhoods.geojson', geojsonOptions);
            // 保存邻域数据的新实体集合。
            let neighborhoods;
            neighborhoodsPromise.then(function(dataSource) {
                // 将新数据作为实体添加到查看器/视图中。
                viewer.dataSources.add(dataSource);
                neighborhoods = dataSource.entities;
                // 获取实体数组。
                let neighborhoodEntities = dataSource.entities.values;
                for (let i = 0; i < neighborhoodEntities.length; i++) {
                    let entity = neighborhoodEntities[i];
                    if (Cesium.defined(entity.polygon)) {
                        // 这里是实体样式代码:
                        // 实体名称。
                        entity.name = entity.properties.neighborhood;
                        // 将多边形材料设置为随机的半透明颜色。
                        entity.polygon.material = Cesium.Color.fromRandom({
                            red : 0.1,
                            maximumGreen : 0.5,
                            minimumBlue : 0.5,
                            alpha : 0.6
                        });
                        // 告诉多边形给地形着色。
                        // 选项 ClassificationType.CESIUM_3D_TILE 将会为3D 区块集着色,
                        // 选项 ClassificationType.BOTH 将同时为3d瓦片 和 地形着色。 (此选项是默认选项)
                        entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;

                        // 生成多边形位置
                        let polyPositions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions;
                        // 获取多边形的平面中心。
                        let polyCenter = Cesium.BoundingSphere.fromPoints(polyPositions).center;
                        // 把多边形的平面中心点,转换到WGS-84坐标系的椭球表面。
                        // WGS-84坐标系,一种国际上采用的地心坐标系,坐标原点为地球质心。
                        polyCenter = Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter);
                        entity.position = polyCenter;
                        // 生成标签
                        entity.label = {
                            text : entity.name,
                            showBackground : true,
                            scale : 0.6,
                            horizontalOrigin : Cesium.HorizontalOrigin.CENTER,
                            verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
                            distanceDisplayCondition : new Cesium.DistanceDisplayCondition(10.0, 8000.0),
                            disableDepthTestDistance : 100.0 // 可以是标签随时可见,不被实体遮挡。
                        };
                    }
                }
            });


            // 以下要从czml文件加载无人机飞行路径。
            let dronePromise = Cesium.CzmlDataSource.load('../Source/SampleData/SampleFlight.czml');
            let drone;  // 无人机。
            dronePromise.then(function(dataSource) {
                // 加载路径的动态效果。
                viewer.dataSources.add(dataSource);
                // 使用czml数据中定义的id获取实体。
                drone = dataSource.entities.getById('Aircraft/Aircraft1');
                // 附加三维模型。
                drone.model = {
                    uri : '../Source/SampleData/Models/CesiumDrone.gltf',
                    minimumPixelSize : 128,  // 最小像素大小.
                    maximumScale : 1000,  // 最大标度.
                    silhouetteColor : Cesium.Color.WHITE,  // 轮廓颜色。
                    silhouetteSize : 2  // 轮廓尺寸。
                };
                // 根据抽样位置添加计算方向。
                drone.orientation = new Cesium.VelocityOrientationProperty(drone.position);
                // 平滑路径插补。
                drone.position.setInterpolationOptions({
                    interpolationDegree : 3,
                    interpolationAlgorithm : Cesium.HermitePolynomialApproximation  // 插补算法:Hermite多项式逼近
                });
            });


            // 加载纽约的建筑物。
            // city保存了整个建筑物实体模型。
            let city = viewer.scene.primitives.add(
                new Cesium.Cesium3DTileset({ url: Cesium.IonResource.fromAssetId(3839) })
            );
            // 调整倾斜高度,使其不漂浮在地形之上。
            let heightOffset = -32;  // 向下偏移量。
            city.readyPromise.then(function(tileset) {
                // 以下要重新定位倾斜模型。
                // boundingSphere, 包容球。
                let boundingSphere = tileset.boundingSphere;
                // 从笛卡尔位置创建一个新的制图实例。结果对象中的值将以弧度表示。
                let cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center);
                // 从以弧度表示的经度和纬度值返回一个Cartesian 3位置。
                let surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
                let offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, heightOffset);
                // 计算两个cartesian类型数据的差异。
                let translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
                tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
                // console.log("tileset:", tileset);
                // console.log("tileset.boundingSphere:", tileset.boundingSphere);
                // console.log("boundingSphere.center:", boundingSphere.center);
                // console.log("cartographic:", cartographic);
                // console.log("surface:", surface);
                // console.log("offset:", offset);
                // console.log("translation:", translation);
                // console.log("tileset.modelMatrix:", tileset.modelMatrix);
            });
            //以下要设置城市建筑的样式。
            let defaultStyle = new Cesium.Cesium3DTileStyle({
                color : "color('white')",
                show : true
            });
            // city.style = defaultStyle;
            let transparentStyle = new Cesium.Cesium3DTileStyle({
                color : "color('white', 0.3)",  // 0,透明,1,不透明。
                show : true
            });
            // city.style = transparentStyle;
            let heightStyle = new Cesium.Cesium3DTileStyle({
                color : {
                    conditions : [
                        ["${height} >= 300", "rgba(45, 0, 75, 0.5)"],
                        ["${height} >= 200", "rgb(102, 71, 151)"],
                        ["${height} >= 100", "rgb(170, 162, 204)"],
                        ["${height} >= 50", "rgb(224, 226, 238)"],
                        ["${height} >= 25", "rgb(252, 230, 200)"],
                        ["${height} >= 10", "rgb(248, 176, 87)"],
                        ["${height} >= 5", "rgb(198, 106, 11)"],
                        ["true", "rgb(127, 59, 8)"]
                    ]
                }
            });
            // city.style = heightStyle;

            // 以下要设置3d Tile Styling的下拉选项对应的样式。
            let tileStyle = document.getElementById('tileStyle');
            // 设置3D实体的样式。
            function set3DTileStyle() {
                let selectedStyle = tileStyle.options[tileStyle.selectedIndex].value;
                if (selectedStyle === 'none') {
                    city.style = defaultStyle;
                } else if (selectedStyle === 'height') {
                    city.style = heightStyle;
                } else if (selectedStyle === 'transparent') {
                    city.style = transparentStyle;
                }
            }

            // 给下拉列表添加“更改”事件,及其执行函数。
            tileStyle.addEventListener('change', set3DTileStyle);


            let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
            // 如果鼠标在兴趣点上,改变实体广告牌的比例和颜色。
            let previousPickedEntity = undefined;
            handler.setInputAction(function(movement) {
                let pickedPrimitive = viewer.scene.pick(movement.endPosition);
                let pickedEntity = (Cesium.defined(pickedPrimitive)) ? pickedPrimitive.id : undefined;
                // 取消突出显示先前选定的实体。
                if (Cesium.defined(previousPickedEntity)) {
                    previousPickedEntity.billboard.scale = 1.0;
                    previousPickedEntity.billboard.color = Cesium.Color.WHITE;
                }
                // 突出显示当前选定的实体。
                if (Cesium.defined(pickedEntity) && Cesium.defined(pickedEntity.billboard)) {
                    pickedEntity.billboard.scale = 2.0;
                    pickedEntity.billboard.color = Cesium.Color.ORANGERED;
                    previousPickedEntity = pickedEntity;
                }
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);


            // 以下要创建视图模式,(自由模式/家视图模式,无人机模式),
            // 通过camera mode下的单选按钮来选择即可。
            // 获取两个模式的单选按钮元素。
            let freeModeElement = document.getElementById('freeMode');
            let droneModeElement = document.getElementById('droneMode');

            // 通过跟踪无人机实体,创建跟踪摄像机
            function setViewMode() {
                if (droneModeElement.checked) {
                    viewer.trackedEntity = drone;
                }
                else {
                    viewer.trackedEntity = undefined;
                    viewer.scene.camera.flyTo(homeCameraView);
                }
            }

            // 为两个元素添加“change”事件及其处理函数。
            freeModeElement.addEventListener('change', setViewMode);
            droneModeElement.addEventListener('change', setViewMode);

            // 双击无人机,转换到无人机模式时, 和
            // 单击右上角的房子,转换到自由模式时,
            // 自动更新UI(Sample NYC Geocaches)
            viewer.trackedEntityChanged.addEventListener(function() {
                if (viewer.trackedEntity === drone) {
                    freeModeElement.checked = false;
                    droneModeElement.checked = true;
                }
                else {
                    freeModeElement.checked = true;
                    droneModeElement.checked = false;
                }
            });

            // 以下要通过Display Options(显示选项)来操作,邻域边界的可见性。
            // 选中Neighborhoods复选框,可见;否则,不可见。
            // neighborhoodsElement,复选框元素。
            let neighborhoodsElement =  document.getElementById('neighborhoods');
            // 给Neighborhoods复选框添加“change”事件,来控制邻域所有实体的可见性。
            neighborhoodsElement.addEventListener('change', function (e) {
                // neighborhoods,所有邻域实体。
                neighborhoods.show = e.target.checked;
            });

            // 以下要通过shadows复选框,来操作/切换视图中的阴影效果。(主要体现在建筑物的阴面。)
            // 获取shadows复选框元素。
            let shadowsElement = document.getElementById('shadows');
            // 给该元素添加“change”事件。
            shadowsElement.addEventListener('change', function (e) {
                // 根据shadows复选框的选中与否,决定视图的阴影有否。
                viewer.shadows = e.target.checked;
            });

            // 最后,等待城市完成初始化,再删除加载指示符。
            // 加载指示符,其实是整个视图上层的一层黑幕布。网速好的情况下不会出现。
            let loadingIndicator = document.getElementById('loadingIndicator');
            loadingIndicator.style.display = 'block';
            // city,整个建筑物实体模型,就绪/解析完成,隐藏加载指示符。
            city.readyPromise.then(function () {
                loadingIndicator.style.display = 'none';
            });
        </script>
    </body>
</html>

猜你喜欢

转载自blog.csdn.net/weixin_42193179/article/details/84930968
今日推荐