cesium 1.59 Imagery Layers Manipulation.html

<!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, maximum-scale=1, minimum-scale=1, user-scalable=no">
    <meta name="description"
          content="Layer imagery from multiple sources, including WMS servers, Bing Maps, ArcGIS Online, OpenStreetMaps, and more, and adjust the alpha of each independently.">
    <meta name="cesium-sandcastle-labels" content="Showcases">
    <title>Imagery Layers Manipulation</title>

    <script type="text/javascript" src="../Sandcastle-header.js"></script>
    <script type="text/javascript" src="../../../ThirdParty/requirejs-2.1.20/require.js"></script>
    <script type="text/javascript">
        if (typeof require === 'function') {
            require.config({
                baseUrl: '../../../Source',
                waitSeconds: 120
            });
        }
    </script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
    @import url(../templates/bucket.css);

    #toolbar {
        background: rgba(42, 42, 42, 0.8);
        padding: 4px;
        border-radius: 4px;
    }

    #toolbar input {
        vertical-align: middle;
        padding-top: 2px;
        padding-bottom: 2px;
    }

    #toolbar table tr {
        transform: translateY(0);
        transition: transform 0.4s ease-out;
    }

    #toolbar table tr.up {
        transform: translateY(33px);
        transition: none;
    }

    #toolbar table tr.down {
        transform: translateY(-33px);
        transition: none;
    }
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
    <table>
        <!--
        知识点:
        data-bind的值的格式类似JSON,键是标签本身的属性,值的viewModel的属性或遍历对象的属性或css中绑定该元素的类名。
        键值对之间用“,”分隔,键值之间用“:”分隔,可以嵌套。
        在html控件中,用$parent代表与其绑定的视图模型viewModel,借此可以访问viewModel的属性或方法。
        用$data,代表foreach:后边循环的每一个元素的值,此处是layer。
        用$index(),代表foreach:后边循环的每一个元素在当前数组的下标。
        其中input标签的data-bind值中,可以用类似valueUpdate: 'input'键值对,规定该值的更新方式。
        data-bind的值的键类别统计如下:
        foreach, css, checked, text, visible, options, optionsText, value, valueUpdate, click。
        其中,click是js里的动作。css, 是UI用户界面的动作。-->

        <!--对viewModel.layers数组进行循环。-->
        <tbody data-bind="foreach: layers">
        <!--$parent绑定viewModel,$data绑定循环的当前layer。css的动态样式up/down,哪个为true哪个执行。-->
        <tr data-bind="css: { up: $parent.upLayer === $data, down: $parent.downLayer === $data }">
            <!--复选框,绑定当前layer的属性show。-->
            <td><input type="checkbox" data-bind="checked: show"></td>
            <td>
                <!--绑定当前layer的属性name。-->
                <span data-bind="text: name, visible: !$parent.isSelectableLayer($data)"></span>
                <!--绑定viewModel.baseLayers(层的数组),选项文本是层名,值是选中的图层。-->
                <select data-bind="visible: $parent.isSelectableLayer($data), options: $parent.baseLayers, optionsText: 'name', value: $parent.selectedLayer"></select>
            </td>
            <td>
                <!--绑定当前layer的属性alpha,值更新方式,input事件,即,当input的value值发生变化时就会触发,不用等到失去焦点。-->
                <input type="range" min="0" max="1" step="0.01" data-bind="value: alpha, valueUpdate: 'input'">
            </td>
            <td>
                <!--升层按钮,绑定单击事件,单击一次提升一层,可见性,该层可以升层。-->
                <button type="button" class="cesium-button"
                        data-bind="click: function() { $parent.raise($data, $index()); }, visible: $parent.canRaise($index())">
                    &#9650;
                </button>
            </td>
            <td>
                <!--降层按钮,绑定单击事件,单击一次降低一层,可见性,该层可以降层。-->
                <button type="button" class="cesium-button"
                        data-bind="click: function() { $parent.lower($data, $index()); }, visible: $parent.canLower($index())">
                    &#9660;
                </button>
            </td>
        </tr>
        </tbody>
    </table>
</div>
<script id="cesium_sandcastle_script">
    function startup(Cesium) {
        'use strict';
        // Sandcastle_Begin
        let viewer = new Cesium.Viewer('cesiumContainer', {
            baseLayerPicker: false  // 不创建“基层拾取器”。
        });
        let imageryLayers = viewer.imageryLayers;
        console.log("imageryLayers:", imageryLayers);

        // 1.创建viewModel对象
        let viewModel = {
            layers: [],  // 该数组要存放的图层,和imageryLayers中的图层,数量相同,顺序相反。
            baseLayers: [],  // baseLayers,包含待选择的所有的基层,选择某个基层后,会用该基层替换掉视图imageryLayers中原来的基层。
            upLayer: null,
            downLayer: null,
            selectedLayer: null,  // 当前选择的基层。
            isSelectableLayer: function (layer) {
                /*此函数用于,判断该层是否是下拉框可选的基层。*/
                return this.baseLayers.indexOf(layer) >= 0;
            },
            raise: function (layer, index) {
                /*此函数用于,使某图层的堆叠顺序,向上提升一层。*/
                imageryLayers.raise(layer);
                viewModel.upLayer = layer;
                viewModel.downLayer = viewModel.layers[Math.max(0, index - 1)];
                updateLayerList();
                window.setTimeout(function () {
                    viewModel.upLayer = viewModel.downLayer = null;
                }, 10);
            },
            lower: function (layer, index) {
                /*此函数用于,使某图层的堆叠顺序,向下下降一层。*/
                imageryLayers.lower(layer);
                viewModel.upLayer = viewModel.layers[Math.min(viewModel.layers.length - 1, index + 1)];
                viewModel.downLayer = layer;
                updateLayerList();
                window.setTimeout(function () {
                    viewModel.upLayer = viewModel.downLayer = null;
                }, 10);
            },
            canRaise: function (layerIndex) {
                /*此函数用于,判断某图层的堆叠顺序,可以向上提升一层吗?
                * layerIndex,该图层在viewModel.layers中的下标。*/
                return layerIndex > 0;
            },
            canLower: function (layerIndex) {
                /*此函数用于,判断某图层的堆叠顺序,可以向下下降一层吗?
                * layerIndex, 该图层在viewModel.layers中的下标。*/
                return layerIndex >= 0 && layerIndex < imageryLayers.length - 1;
            }
        };
        let baseLayers = viewModel.baseLayers;

        // 2.监测viewModel中的属性
        Cesium.knockout.track(viewModel);

        // 创建图层(基层、附加层)并添加到视图。
        setupLayers();
        // 把imageryLayers中的图层,倒序同步到viewModel.layers数组中。
        updateLayerList();

        // 3.将viewModel对象与html控件绑定
        let toolbar = document.getElementById('toolbar');
        Cesium.knockout.applyBindings(viewModel, toolbar);

        // 4.监听viewModel的selectedLayer属性。
        // 该属性的变更,是客户端动态操作,并同步到viewModel的selectedLayer属性。
        // 从而可以实现,对该属性的监听,动态操作视图中的基层的变更。
        Cesium.knockout.getObservable(viewModel, 'selectedLayer').subscribe(function (baseLayer) {
            // 以下要处理对下拉基层选择器的更改。baseLayer,刚选择的基层。
            // 1.找到当前视图中基层在viewModel.layers中的下标,保存到activeLayerIndex。
            let activeLayerIndex = 0;
            let numLayers = viewModel.layers.length;
            for (let i = 0; i < numLayers; ++i) {
                if (viewModel.isSelectableLayer(viewModel.layers[i])) {
                    activeLayerIndex = i;
                    break;
                }
            }
            // activeLayer,当前基层。
            let activeLayer = viewModel.layers[activeLayerIndex];
            // 获取当前基层的属性show, alpha.
            let show = activeLayer.show;
            let alpha = activeLayer.alpha;
            // remove(layer, destroy) → Boolean
            imageryLayers.remove(activeLayer, false);
            // add(layer, index)
            // 把更改后的基层,添加到视图中,相应的下标位置。
            // 此处numLayers - 1 - activeLayerIndex,是根据该图层在viewModel.layers中的位置,
            // 计算该图层应该在imageryLayers数组中的位置。
            imageryLayers.add(baseLayer, numLayers - activeLayerIndex - 1);
            // 可以先添加,再设置该层的属性。
            baseLayer.show = show;
            baseLayer.alpha = alpha;
            updateLayerList();
        });

        /*以下是工具函数。*/
        function setupLayers() {
            /*此函数用于,创建各种层。*/
            // 1.创建基层。
            addBaseLayerOption('Bing Maps Aerial', undefined);  // 当前基层。
            addBaseLayerOption(
                    'Bing Maps Road',
                    new Cesium.BingMapsImageryProvider({
                        url: 'https://dev.virtualearth.net',
                        mapStyle: Cesium.BingMapsStyle.ROAD
                    }));
            addBaseLayerOption(
                    'ArcGIS World Street Maps',
                    new Cesium.ArcGisMapServerImageryProvider({
                        url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer'
                    }));
            addBaseLayerOption(
                    'OpenStreetMaps',
                    Cesium.createOpenStreetMapImageryProvider());
            addBaseLayerOption(
                    'MapQuest OpenStreetMaps',
                    Cesium.createOpenStreetMapImageryProvider({
                        url: 'https://otile1-s.mqcdn.com/tiles/1.0.0/osm/'
                    }));
            addBaseLayerOption(
                    'Stamen Maps',
                    Cesium.createOpenStreetMapImageryProvider({
                        url: 'https://stamen-tiles.a.ssl.fastly.net/watercolor/',
                        fileExtension: 'jpg',
                        credit: 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under CC BY SA.'
                    }));
            addBaseLayerOption(
                    'Natural Earth II (local)',
                    Cesium.createTileMapServiceImageryProvider({
                        url: Cesium.buildModuleUrl('Assets/Textures/NaturalEarthII')
                    }));
            addBaseLayerOption(
                    'USGS Shaded Relief (via WMTS)',
                    new Cesium.WebMapTileServiceImageryProvider({
                        url: 'http://basemap.nationalmap.gov/arcgis/rest/services/USGSShadedReliefOnly/MapServer/WMTS',
                        layer: 'USGSShadedReliefOnly',
                        style: 'default',
                        format: 'image/jpeg',
                        tileMatrixSetID: 'default028mm',
                        maximumLevel: 19,
                        credit: 'U. S. Geological Survey'
                    }));

            // 2.以下要创建附加层,并添加到视图,后来居上。
            addAdditionalLayerOption(
                    'United States GOES Infrared',
                    new Cesium.WebMapServiceImageryProvider({
                        url: 'https://mesonet.agron.iastate.edu/cgi-bin/wms/goes/conus_ir.cgi?',
                        layers: 'goes_conus_ir',
                        credit: 'Infrared data courtesy Iowa Environmental Mesonet',
                        parameters: {
                            transparent: 'true',
                            format: 'image/png'
                        }
                    })
            );
            addAdditionalLayerOption(
                    'United States Weather Radar',
                    new Cesium.WebMapServiceImageryProvider({
                        url: 'https://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi?',
                        layers: 'nexrad-n0r',
                        credit: 'Radar data courtesy Iowa Environmental Mesonet',
                        parameters: {
                            transparent: 'true',
                            format: 'image/png'
                        }
                    })
            );
            addAdditionalLayerOption(
                    'TileMapService Image',
                    Cesium.createTileMapServiceImageryProvider({
                        url: '../images/cesium_maptiler/Cesium_Logo_Color'
                    }),
                    0.2
            );
            addAdditionalLayerOption(
                    'Single Image',
                    new Cesium.SingleTileImageryProvider({
                        url: '../images/Cesium_Logo_overlay.png',
                        rectangle: Cesium.Rectangle.fromDegrees(-115.0, 38.0, -107, 39.75)
                    }),
                    1.0
            );
            addAdditionalLayerOption(
                    'Grid',
                    new Cesium.GridImageryProvider(), 1.0, false
            );
            addAdditionalLayerOption(
                    'Tile Coordinates',
                    new Cesium.TileCoordinatesImageryProvider(), 1.0, false
            );
        }

        function addBaseLayerOption(name, imageryProvider) {
            /*此函数用于,创建基层,并添加到viewModel.baseLayers数组。*/
            let layer;
            if (typeof imageryProvider === 'undefined') {
                layer = imageryLayers.get(0);
                // 初始化当前基层。
                viewModel.selectedLayer = layer;
            } else {
                layer = new Cesium.ImageryLayer(imageryProvider);
            }

            layer.name = name;
            baseLayers.push(layer);
        }

        function addAdditionalLayerOption(name, imageryProvider, alpha, show) {
            /*此函数用于,创建附加层,添加到视图,并为其设置alpha, show, name属性。*/
            let layer = imageryLayers.addImageryProvider(imageryProvider);
            layer.alpha = Cesium.defaultValue(alpha, 0.5);
            layer.show = Cesium.defaultValue(show, true);
            layer.name = name;
            // 监听该附加层的alpha,show,name属性。
            Cesium.knockout.track(layer, ['alpha', 'show', 'name']);
        }

        function updateLayerList() {
            /*此函数用于,清空viewModel.layers数组,
            并把imageryLayers中的图层,倒序添加到viewModel.layers数组中。
            这是为了实现,在html控件上,上层的图层在控件上边显示 的效果。
            当创建并添加图层、移动图层、变更基层时,需要调用此函数,
            以确保视图图层和viewModel中图层状态的同步。*/
            let numLayers = imageryLayers.length;
            // 清空viewModel.layers数组。
            viewModel.layers.splice(0, viewModel.layers.length);
            for (let i = numLayers - 1; i >= 0; --i) {
                viewModel.layers.push(imageryLayers.get(i));
            }
        }

        //Sandcastle_End
        Sandcastle.finishedLoading();
    }

    if (typeof Cesium !== 'undefined') {
        startup(Cesium);
    } else if (typeof require === 'function') {
        require(['Cesium'], startup);
    }
</script>
</body>
</html>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值