1.功能说明:

  鼠标绘制多边形进行查询,通过多边形范围,调用Geoserver发布的WFS服务,查询相交的地图要素,将返回结果高亮显示。

  单击高亮显示的要素,显示要素的属性信息。

2.网页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="Draw point on terrain with mouse clicks.">
    <meta name="cesium-sandcastle-labels" content="Showcases">
    <title>WFS属性查询</title>
    <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
    <script type="text/javascript" src="Sandcastle-header.js"></script>
    <script type="module" src="load-cesium-es6.js"></script>
    <script src="./Build/CesiumUnminified/Cesium.js"></script>
    <script>window.CESIUM_BASE_URL = "./Build/CesiumUnminified/";</script>
  </head>
  <body  class="sandcastle-loading"  data-sandcastle-bucket="bucket-requirejs.html">
    <style>
    @import url(bucket.css);
        html,
        body,
        #cesiumContainer {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        overflow: hidden;
        }
    </style>
    <div id="cesiumContainer" class="fullSize"></div>
    <div id="loadingOverlay"><h1>Loading...</h1></div>
    <div id="toolbar">
      <table class="infoPanel">
        <tbody>
          <tr>
            <td>左键单击绘制点,右击结束线矩形框绘制。</td>
          </tr>
        </tbody>
      </table>
    </div>
    <div id="infowindow" style="position:absolute;top:10px;right:10px;z-index:999;background:rgb(18, 100, 138);width:200px;height:50px;font-size:13px;display:none;line-height:25px;"></div>
    <script src="./code.js"> </script>
</body>
</html>

3.编写的code.js代码:

Cesium.Ion.defaultAccessToken='你的Token';
window.startup = async function (Cesium) {
    'use strict';
    //增加视图区
    const viewer = new Cesium.Viewer("cesiumContainer", {
        geocoder: false,
        homeButton: true,
        sceneModePicker: false,
        fullscreenButton: false,
        vrButton: false,
        baseLayerPicker: false,
        infoBox: false,
        selectionIndicator: false,
        animation: false,
        timeline: false,
        shouldAnimate: true,
        navigationHelpButton: false,
        navigationInstructionsInitiallyVisible: false,
        terrainProvider: Cesium.createWorldTerrain(),
        imageryProvider: new Cesium.UrlTemplateImageryProvider({
            //url: 'http://mt0.google.cn/vt/lyrs=t,r&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}',
            //url: 'https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
            url: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}",
            //tilingScheme : new Cesium.GeographicTilingScheme(),
            credit: ''
        }),
    });
    //绘制geojson图层样式
    var geoJsonStyle = {
        stroke: Cesium.Color.YELLOW,
        strokeWidth: 3,
        fill: Cesium.Color.YELLOW.withAlpha(0.1)
      };
    var geoserverUrl = 'http://127.0.0.1:8180/geoserver/NtuWrokspace';
    viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
        Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
        );
        function createPoint(worldPosition) {
            const point = viewer.entities.add({
                position: worldPosition,
                point: {
                color: Cesium.Color.RED,
                pixelSize: 5,
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
                },
            });
            return point;
        }
        let drawingMode = "polygon";
        function drawShape(positionData) {
            let shape;
            if (drawingMode === "rectangle") {

            } else if (drawingMode === "polygon") {
                shape = viewer.entities.add({
                polygon: {
                    hierarchy: positionData,
                    material: new Cesium.ColorMaterialProperty(
                    Cesium.Color.RED.withAlpha(0.7)
                    ),
                },
                }); 
            }
            return shape;
        }
         /*空间查询图层
        *@method queryByPolygon
        *@param polygon 空间范围
        *@param typeName 图层名称
        *@return null
        */
        function queryByPolygon(polygon, typeName, callback){
            var filter =
            '<Filter xmlns="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml">';
            /*filter += '<And>';*/
            filter += '<Intersects>';
            filter += '<PropertyName>the_geom</PropertyName>';
            filter += '<gml:Polygon>';
            filter += '<gml:outerBoundaryIs>';
            filter += '<gml:LinearRing>';
            filter += '<gml:coordinates>' + polygon + '</gml:coordinates>';
            filter += '</gml:LinearRing>';
            filter += '</gml:outerBoundaryIs>';
            filter += '</gml:Polygon>';
            filter += '</Intersects>';
            /*filter += '<PropertyIsLike wildCard="*" singleChar="#" escapeChar="!">';
            filter += '<PropertyName>map_num</PropertyName>';
            filter += '<Literal>*201911_440114*</Literal>';
            filter += '</PropertyIsLike>'; */
            /*filter += '</And>';*/
            filter += '</Filter>';
            var urlString = geoserverUrl + '/ows';
            var param = {
            service: 'WFS',
            version: '1.0.0',
            request: 'GetFeature',
            typeName: typeName,
            outputFormat: 'application/json',
            filter: filter
            };
            var geojsonUrl = urlString + getParamString(param, urlString);
            $.ajax({
                url: geojsonUrl,
                async: true,
                type:'GET',
                dataType: 'json',
                success(result) {
                    callback(result);
                },
                error(err) {
                    console.log(err);
                }
            })
        }

        function getParamString(obj, existingUrl, uppercase){
            var params = [];
            for (var i in obj) {
                params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i]));
            }
            return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&');    
        }
        /*
        * 图层空间查询回调函数
        */
        function callbackLastQueryWFSService(data){
            console.log('data',data);
            if(data && data.features.length>0){
            clearGeojsonLayer();
            loadGeojsonLayer(data);
            }
        }
        /*
        * 绘制图形函数
        */
        function loadGeojsonLayer(geojson){
            var promise = Cesium.GeoJsonDataSource.load(geojson,geoJsonStyle);
            promise.then(function(dataSource) {
                viewer.dataSources.add(dataSource);
                viewer.zoomTo(dataSource);
            }).otherwise(function(error){
                //Display any errrors encountered while loading.
                window.alert(error);
            });
        }
        /*
        * 清空绘制图形函数
        */
        function clearGeojsonLayer(){
            viewer.dataSources.removeAll();
        }

        function clearMap(){
            clearGeojsonLayer();
        }

        function getExtentByPoints(points) {
            if (points) {
                // 指定世界范围
                let lonMin = 180;
                let lonMax = -180;
                let latMin = 90;
                let latMax = -180;
                points.forEach(function (point) {
                    const longitude = point[0];
                    const latitude = point[1];
                    // 计算边界
                    lonMin = longitude < lonMin ? longitude : lonMin;
                    latMin = latitude < latMin ? latitude : latMin;
                    lonMax = longitude > lonMax ? longitude : lonMax;
                    latMax = latitude > latMax ? latitude : latMax;
                });
                const xRange = lonMax - lonMin ? lonMax - lonMin : 1;
                const yRange = latMax - latMin ? latMax - latMin : 1;
                // 返回数据
                return [lonMin - xRange / 10, latMin - yRange / 10, lonMax + xRange / 10, latMax + yRange / 10];
            }
            return [-180,-90,180,90];
        }
        /**
         * @todo 弧度坐标转经纬度坐标
         * @param {Cartographic} cartographic - 弧度坐标
         * @return {Object} - {longitude: x, latitude: y, height: h} - 返回经纬度
         */
        function cartographicToDegrees(cartographic) {
            const result = {};
            result.longitude = Cesium.Math.toDegrees(cartographic.longitude);
            result.latitude = Cesium.Math.toDegrees(cartographic.latitude);
            if (cartographic.height > 0) {
                result.height = cartographic.height;
            }
            return result;
        }
        /**
         * @todo 获取 Cartesian3 四至范围
         * @param {Cartesian3} cartesian3s - 世界坐标对象
         * @return {*[]}
         */
        function getExtentByCartesian3(cartesian3s) {

            if(cartesian3s instanceof Array && cartesian3s.length>0){
                const points = [];
                for (let i = 0; i < cartesian3s.length; i++) {
                    const cartesian3 = cartesian3s[i];
                    // 将 cartesian3 转为经纬度数组

                const cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
                const point = cartographicToDegrees(cartographic);
                    points.push([point.longitude,point.latitude]);
                }
                return getExtentByPoints(points);
            }
        }

        let activeShapePoints = [];
        let activeShape;
        let floatingPoint;
        //窗口事件句柄
        const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
        handler.setInputAction(function (event) {
        const ray = viewer.camera.getPickRay(event.position);//根据鼠标点击坐标和相机坐标构建射线
        const earthPosition = viewer.scene.globe.pick(ray, viewer.scene);//射线与球面求交,在地面的交点
        // `earthPosition` will be undefined if our mouse is not over the globe.
        if (Cesium.defined(earthPosition)) //鼠标点击在地球范围内
        {
            if (activeShapePoints.length === 0) {
                floatingPoint = createPoint(earthPosition);
                activeShapePoints.push(earthPosition);
                const dynamicPositions = new Cesium.CallbackProperty(function () {
                    if (drawingMode === "polygon") {
                        return new Cesium.PolygonHierarchy(activeShapePoints);
                    }
                    return activeShapePoints;
                }, false);//回调函数
                activeShape = drawShape(dynamicPositions);
            }
            activeShapePoints.push(earthPosition);
           // createPoint(earthPosition);
        }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);//鼠标左键

        handler.setInputAction(function (event) {
        if (Cesium.defined(floatingPoint)) {
            const ray = viewer.camera.getPickRay(event.endPosition);
            const newPosition = viewer.scene.globe.pick(ray, viewer.scene);
            if (Cesium.defined(newPosition)) {
            floatingPoint.position.setValue(newPosition);
            activeShapePoints.pop();
            activeShapePoints.push(newPosition);
            }
        }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);//鼠标移动
        //移除临时绘制图像.
        function terminateShape() {
            activeShapePoints.pop();
           // drawShape(activeShapePoints);
            viewer.entities.remove(floatingPoint);
            viewer.entities.remove(activeShape);
            floatingPoint = undefined;
            activeShape = undefined;
            activeShapePoints = [];
        }
        handler.setInputAction(function (event) {    
            var polygon = drawShape(activeShapePoints);
            //polygon.setVisible(false);
            var extent =getExtentByCartesian3(activeShapePoints);   
            viewer.entities.remove(polygon);
            terminateShape();
            drawingMode = "unknown";
            if(extent && extent.length>0){
                     //构造polygon 
                     polygon = '';
                     polygon += extent[0] + ',' + extent[1] + ' ' ;
                     polygon += extent[2] + ',' + extent[1] + ' ' ;
                     polygon += extent[2] + ',' + extent[3] + ' ' ;
                     polygon += extent[0] + ',' + extent[3] + ' ' ;
                     polygon += extent[0] + ',' + extent[1] + ' ' ;
           }
           console.log('polygon',polygon);
           if(polygon){
               queryByPolygon(polygon,'NtuWrokspace:省界_region',callbackLastQueryWFSService);
            }

        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);//鼠标右键


    var highlightFace = null;
    viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
         var pickedFeature = viewer.scene.pick(movement.position);
         console.log('pickedFeature',pickedFeature);
         if(pickedFeature){
             //判断之前是否有高亮面存在
             if (highlightFace) {
                 highlightFace.material = highlightFace.material0;
             }
             if(pickedFeature.id.polygon.material){
                 pickedFeature.id.polygon.material0 = pickedFeature.id.polygon.material;
                 pickedFeature.id.polygon.material = Cesium.Color.DEEPSKYBLUE.withAlpha(0.8);
                 highlightFace = pickedFeature.id.polygon;
                 console.log('properties',pickedFeature.id.properties);
                //气泡窗口显示
                var content =
                    "<div>"+
                    "<span>图斑编号:</span><span>"+pickedFeature.id.properties.CODE+"</span></br>"+
                    "<span>图斑描述::</span><span>"+pickedFeature.id.properties.NAME+"</span></br>"+
                    "</div>";
                $("#infowindow").show();
                $("#infowindow").empty();
                $("#infowindow").append(content);
             }
         }
         else{
            if (highlightFace) {
                 highlightFace.material = highlightFace.material0;
            }
            $("#infowindow").hide();
         }
     }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    Sandcastle.addDefaultToolbarButton("框选查询", function () {
        terminateShape();
        drawingMode = "polygon";
    });

      //Example 2: Load with basic styling options.
    Sandcastle.addToolbarButton("点选查询", function () {
        clearMap();
        drawingMode = "unknown";
    });

    Sandcastle.reset = function () {
        viewer.dataSources.removeAll();

        //Set the camera to a US centered tilted view and switch back to moving in world coordinates.
        viewer.camera.lookAt(Cesium.Cartesian3.fromDegrees(115.0, 45.0),
          new Cesium.Cartesian3(0.0, -4790000.0, 3930000.0)
        );
        viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
    };
      //Sandcastle_End
    Sandcastle.finishedLoading();

};
if (typeof Cesium !== 'undefined') {
    window.startupCalled = true;
    window.startup(Cesium).catch((error) => {
      "use strict";
      console.error(error);
    });
}

4.效果如下: