arcgis for js点击聚合要素查询其包含的所有要素

功能说明

上一篇讲了实现聚合效果, 但是点击聚合效果无法获取到该聚合点包含的所有点信息

这一篇是对如何实现该功能的案例

实现

各属性说明需要自行去官网查阅

官网案例

聚合API

没空说废话了, 加班到12点,得休息了, 直接运行代码看效果就行, 相关重点和注意事项都在代码注释里
该案例效果非实际项目效果, 提取出来的更通俗易懂

案例效果:

html 复制代码
<!DOCTYPE html>
<html lang="zn">
  <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>Document</title>

    <style>
      body {
        margin: 0;
      }
      #mapview {
        position: absolute;
        width: 100%;
        height: 100%;
      }
      * {
        margin: 0;
        padding: 0;
      }
    </style>

    <link rel="stylesheet" href="https://js.arcgis.com/4.23/esri/themes/light/main.css" />
    <script src="https://js.arcgis.com/4.23/"></script>
  </head>
  <body>
    <div id="mapview"></div>

    <script>
      require([
        'esri/Map',
        'esri/views/MapView',
        'esri/layers/FeatureLayer',
        'esri/Graphic'
      ], function (Map, MapView, FeatureLayer, Graphic) {
        // 初始化底图
        window.map = new Map({
          basemap: 'dark-gray-vector'
        })

        // 创建2维视图
        let view = new MapView({
          container: 'mapview',
          map: map,
          zoom: 11,
          center: [104.783916597735, 32.55699155692144] // 设置地图的初始化中心点坐标
        })

        // 生成100个随机点
        var points = generateRandomPointsInPolygon(
          [
            [
              [104.64487088240317, 32.66500681729125],
              [104.91060269392625, 32.6635616904849],
              [104.88210690535206, 32.54642886312837],
              [104.68812954939528, 32.54787588095771]
            ]
          ],
          100
        )

        // 创建聚合点
        const features = points.map((point, index) => ({
          geometry: {
            type: 'point',
            x: point[0],
            y: point[1]
          },
          attributes: {
            ObjectID: Math.random(),
            name: `点${index + 1}`
          }
        }))
        if (!features.length) {
          return
        }
        console.log(features)

        const featureLayer = new FeatureLayer({
          source: features,
          title: '生态因子点位图层',
          objectIdField: 'ObjectID',
          fields: [{ name: 'name', type: 'string' }],
          outFields: ['*'],
          popupTemplate: {
            title: '{name}'
          },
          // 渲染成简单圆点
          renderer: {
            type: 'simple',
            symbol: {
              type: 'simple-marker',
              color: 'red',
              size: '10px',
              outline: {
                width: 1,
                color: '#fff'
              }
            }
          },
          // 渲染额外的文本图形
          labelingInfo: [
            {
              symbol: {
                type: 'text',
                color: '#fff',
                // haloSize: 1,
                // haloColor: '#fff',
                backgroundColor: 'rgba(27,140,155,0.7)',
                // xoffset: -22,
                yoffset: 15,
                horizontalAlignment: 'center',
                font: { family: 'sans-serif', size: 8 }
              },
              labelPlacement: 'center-center',
              labelExpressionInfo: { expression: '$feature.name' }
            }
          ],
          // 处理聚合
          featureReduction: {
            type: 'cluster',
            clusterRadius: '40px',
            clusterMinSize: '20px',
            clusterMaxSize: '30px',
            maxScale: 10000,
            // 聚合的内置弹窗
            popupTemplate: {
              title: '包含 {cluster_count} 个点位.',
              fieldInfos: [
                { fieldName: 'cluster_count', format: { places: 0, digitSeparator: true } }
              ]
            },
            // popupEnabled: false,
            // 额外的文本图形
            labelingInfo: [
              {
                deconflictionStrategy: 'none',
                labelExpressionInfo: {
                  title: '数量',
                  expression: 'Text("聚合点:" + $feature.cluster_count + "个", "#,###")'
                },
                symbol: {
                  type: 'text',
                  color: '#ff0000',
                  haloSize: 1,
                  haloColor: '#fff',
                  // backgroundColor: 'rgba(27,140,155,0.7)',
                  // xoffset: -11.5,
                  // yoffset: 8,
                  horizontalAlignment: 'left',
                  font: { family: 'sans-serif', size: 12 }
                },
                labelPlacement: 'above-center'
              }
            ]
          }
        })
        map.add(featureLayer)

        // 重点
        view.whenLayerView(featureLayer).then(layerView => {
          // 添加点击
          view.on('click', async event => {
            const { longitude, latitude } = event.mapPoint
            // console.log('>>> 点击的坐标: ')
            console.log(`${longitude}, ${latitude}`)

            // 匹配元素
            const { results } = await view.hitTest(event)

            // 没有匹配到元素退出
            if (!results?.length) {
              return
            }

            // 取第一个元素, 如果要处理多个元素, 自行遍历
            const { graphic, layer } = results[0]

            // 判断该元素是否为聚合点
            if (graphic.isAggregate === true) {
              const aggregateId = graphic.getObjectId() // 聚合ID
              // const aggregateId = graphic.attributes.aggregateId // 同上一样

              // 判断对应图层, 可以根据需要去掉
              if (graphic?.layer === featureLayer) {
                // 创建查询对象
                /**
                 * 重点, 一定要从layerView创建, 而不是featureLayer创建
                 * 我在这里踩了个大坑, 哎
                 */
                const query = layerView.createQuery()
                query.aggregateIds = [aggregateId]

                // 这里同样, 一定要从layerView查询, 而不是featureLayer查询
                const { features } = await layerView.queryFeatures(query)
                console.log('>>>>>>>> 聚合的要素', features)

                alert('聚合的要素为:' + features.map(item => item.attributes.name).join(','))
              }
            }
          })
        })

        // 生成随机点
        function generateRandomPointsInPolygon(polygonCoords, number) {
          // 判断是否在图形内
          function isPointInsidePolygon(point, polygonCoords) {
            let crossings = 0

            for (let i = 0, j = polygonCoords[0].length - 1; i < polygonCoords[0].length; j = i++) {
              const xi = polygonCoords[0][i][0]
              const yi = polygonCoords[0][i][1]
              const xj = polygonCoords[0][j][0]
              const yj = polygonCoords[0][j][1]

              if (
                ((yi <= point[1] && point[1] < yj) || (yj <= point[1] && point[1] < yi)) &&
                point[0] < ((xj - xi) * (point[1] - yi)) / (yj - yi) + xi
              ) {
                crossings++
              }
            }
            return crossings % 2 !== 0
          }

          // 存储生成的随机点
          let randomPoints = []

          // 获取多边形的最小和最大经纬度范围
          let minLat = polygonCoords[0][0][1]
          let maxLat = polygonCoords[0][0][1]
          let minLng = polygonCoords[0][0][0]
          let maxLng = polygonCoords[0][0][0]

          for (let i = 0; i < polygonCoords[0].length; i++) {
            const lat = polygonCoords[0][i][1]
            const lng = polygonCoords[0][i][0]

            if (lat < minLat) {
              minLat = lat
            }
            if (lat > maxLat) {
              maxLat = lat
            }
            if (lng < minLng) {
              minLng = lng
            }
            if (lng > maxLng) {
              maxLng = lng
            }
          }

          for (let i = 0; i < number; i++) {
            let isPointInside = false
            let randomPoint

            // 不断尝试生成随机点,直到点在多边形内
            while (!isPointInside) {
              // 在多边形的经纬度范围内随机生成一个点
              const randomLat = minLat + (maxLat - minLat) * Math.random()
              const randomLng = minLng + (maxLng - minLng) * Math.random()

              randomPoint = [randomLng, randomLat]

              // 使用射线法判断点是否在多边形内
              isPointInside = isPointInsidePolygon(randomPoint, polygonCoords)
            }
            randomPoints.push(randomPoint)
          }
          return randomPoints
        }
      })
    </script>
  </body>
</html>
相关推荐
猫猫不是喵喵.20 分钟前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~1 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华2 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子4 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅4 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni5 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学6 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端
赵庆明老师6 小时前
Vben精讲:21-详解web-antd:tsconfig.json
前端·json·vim
wc887 小时前
微软EDGE浏览器功能学习
前端·学习·edge