当前位置: 首页 > news >正文

【2025最新】ArcGIS 点聚合功能实现全教程(进阶版)

ArcGIS 点聚合功能实现全教程(进阶版)

本教程聚焦点数据生成、多类别样式配置、聚合开关控制及类别筛选等核心功能的进阶实现逻辑,深入解析点聚合功能进阶用法。本文为《【2025最新】ArcGIS for JS点聚合功能实现》进阶版,关于地图初始化、模块导入、基础组件配置等入门内容不再赘述。

文章目录

  • ArcGIS 点聚合功能实现全教程(进阶版)
    • 效果图
    • 实现功能
    • 一、核心功能实现步骤
      • (一)点要素图层创建
      • (二)点聚合功能配置
      • (三)辅助功能实现
    • 二、其他
    • 三、全部代码
      • index.html
      • tiandituLoader.js

工具 /插件/系统 名版本说明
ArcGIS for JavaScript4.33适用4.28 - 4.33版本

效果图

效果1效果2
在这里插入图片描述在这里插入图片描述

实现功能

  1. 聚合开关切换:通过 “启用 / 禁用聚合” 按钮控制聚合状态,点击时切换图层featureReduction属性(聚合模式 / 非聚合模式),并同步更新按钮文本,实现交互化聚合控制。
  2. 类别条件筛选:通过下拉框提供 “全部 + 4 个类别” 的筛选选项,选择后触发图层筛选逻辑,仅显示符合category条件的点要素,同时关闭当前弹窗避免信息干扰,实现精准数据筛选。
  3. 聚合样式:不同类别的聚合簇采用对应的图标。

一、核心功能实现步骤

(一)点要素图层创建

  1. 定义数据结构:设置字段信息,包含唯一标识、类别与数值字段
fields: [{name: "ObjectID",alias: "ObjectID",type: "oid"}, {name: "category",alias: "类别",type: "integer"}, {name: "value",alias: "值",type: "integer"}]
  1. 生成随机点数据:通过generateRandomPoints函数创建 5000 个随机点,经度范围 0-119,纬度范围 30-60,随机分配 4 个类别
function generateRandomPoints(count) {const points = [];for (let i = 0; i < count; i++) {const lon = (Math.random() * 119); // 经度范围const lat = (Math.random() * 30) + 30;  // 纬度范围// 随机分配类别const category = Math.floor(Math.random() * 4);points.push({geometry: {type: "point",longitude: lon,latitude: lat},attributes: {ObjectID: i,category: category,value: Math.floor(Math.random() * 100)}});}return points;}
  1. 设置要素样式:采用唯一值渲染,为 4 个类别分别设置不同样式,包括简单圆形标记与图片标记
renderer: {type: "unique-value",field: "category",uniqueValueInfos: [{value: 0, symbol: {type: 'simple-marker',color: [24, 174, 255, 0.5],size: 16,style: "circle",outline: {color: [24, 174, 255, 0.8],width: 2}},label: "类别1"},// 其他类别样式配置...]}
  1. 配置弹窗模板:点击单点时显示类别与数值信息
popupTemplate: {title: "{category}",content: "类别:{category},值:{value}",}

(二)点聚合功能配置

  1. 生成聚合配置:通过generateClusterConfig函数创建聚合参数,包含弹窗模板、标签样式、最小聚合尺寸与最大聚合比例尺
async function generateClusterConfig(layer) {const popupTemplate = await clusterPopupCreator.getTemplates({ layer }).then(res => res.primaryTemplate.value);const { labelingInfo, clusterMinSize } = await clusterLabelCreator.getLabelSchemes({ layer, view }).then(res => res.primaryScheme);return {type: "cluster",popupTemplate,labelingInfo,clusterMinSize,maxScale: 50000};}
  1. 实现聚合开关:通过toggleClustering函数切换聚合状态,点击按钮时修改featureReduction属性
function toggleClustering() {let fr = layer.featureReduction;layer.featureReduction = fr && fr.type === "cluster" ? null : featureReduction;toggleButton.innerText = toggleButton.innerText === "启用聚合" ? "禁用聚合" : "启用聚合";}

(三)辅助功能实现

  1. 图例组件:创建图例并关联地图视图,展示各类别样式说明
const legend = new Legend({view,container: "legendDiv",});
  1. 类别筛选:监听下拉框变化,通过layerView.filter设置筛选条件,筛选特定类别点数据
filterSelect.addEventListener("change", (event) => {const newValue = event.target.value;const whereClause = newValue ? \`category = ${newValue}\` : null;layerView.filter = { where: whereClause };view.closePopup();});
  1. 聚合弹窗样式优化:修改聚合区域边界样式,增强视觉辨识度
reactiveUtils.whenOnce(() => view.popup.viewModel).then(() => {view.popup.viewModel.selectedClusterBoundaryFeature.symbol = {type: "simple-fill",style: "solid",color: "rgba(50,50,50,0.8)",outline: { width: 0.5, color: "rgba(50,50,50,0.8)" }};});

二、其他

  1. 符号类型匹配:确保点要素使用simple-markerpicture-marker类型,避免因符号类型错误导致渲染失效

  2. 类别值匹配:筛选下拉框的value属性需与category字段值一致(0-3),原示例中值为 1-4 需修正为 0-4

  3. 按钮初始文本:聚合按钮初始文本应设为 “启用聚合”,与切换逻辑匹配

  4. 要素加载时机:所有依赖图层的操作需在layer.when()回调中执行,确保图层加载完成

三、全部代码

index.html

<!doctype html>
<html lang="zh-CN"><head><meta charset="utf-8" /><meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /><title>ArcGIS 点聚合基础示例</title><link rel="stylesheet" href="https://js.arcgis.com/4.33/esri/themes/light/main.css" /><script src="https://js.arcgis.com/4.33/"></script><style>html,body,#viewDiv {height: 100%;width: 100%;margin: 0;padding: 0;}#infoDiv {background: white;padding: 10px;}</style><script type="module">import { loadTiandituBasemap } from './js/tiandituLoader.js';const [Map,MapView,FeatureLayer,Legend,Expand,clusterLabelCreator,clusterPopupCreator,reactiveUtils,] = await $arcgis.import(["@arcgis/core/WebMap.js","@arcgis/core/views/MapView.js","@arcgis/core/layers/FeatureLayer.js","@arcgis/core/widgets/Legend.js","@arcgis/core/widgets/Expand.js","@arcgis/core/smartMapping/labels/clusters.js","@arcgis/core/smartMapping/popup/clusters.js","@arcgis/core/core/reactiveUtils.js",]);const { tileInfo, config, getUrlTemplate, tiandituBasemap, Basemap, WebTileLayer } = await loadTiandituBasemap();const layer = new FeatureLayer({source: generateRandomPoints(5000),title: "点聚合",fields: [{name: "ObjectID",alias: "ObjectID",type: "oid"}, {name: "category",alias: "类别",type: "integer"}, {name: "value",alias: "值",type: "integer"}],outFields: ["*"],popupTemplate: {title: "{category}",content: "类别:{category},值:{value}",},renderer: {type: "unique-value",field: "category",uniqueValueInfos: [{value: 0, symbol: {type: 'simple-marker', // 点要素专用符号类型(核心修复点)color: [24, 174, 255, 0.5], // 半透明蓝色(与原需求一致)size: 16, // 点的大小(像素,建议12-20,适配视觉)style: "circle", // 点的形状(circle/方形/square/三角形/triangle等)outline: { // 点的描边(增强辨识度)color: [24, 174, 255, 0.8],width: 2}},label: "类别1"},{value: 1, symbol: {type: "picture-marker",url: "https://picsum.photos/20/20", // 20x20的图片width: "20px",height: "20px",yoffset: "10px" // 图标偏移,使底部对准点位置}, label: "类别2"},{value: 2, symbol: {type: 'simple-marker', // 点要素专用符号类型(核心修复点)color: [24, 14, 255, 0.5], // 半透明蓝色(与原需求一致)size: 16, // 点的大小(像素,建议12-20,适配视觉)style: "circle", // 点的形状(circle/方形/square/三角形/triangle等)outline: { // 点的描边(增强辨识度)color: [24, 14, 255, 0.8],width: 2}}, label: "类别3"},{value: 3, symbol: {type: 'simple-marker', // 点要素专用符号类型(核心修复点)color: [24, 144, 55, 0.5], // 半透明蓝色(与原需求一致)size: 16, // 点的大小(像素,建议12-20,适配视觉)style: "circle", // 点的形状(circle/方形/square/三角形/triangle等)outline: { // 点的描边(增强辨识度)color: [24, 144, 55, 0.5],width: 2}}, label: "类别4"}]}});const map = new Map({basemap: tiandituBasemap,layers: [layer],});const view = new MapView({container: "viewDiv",map,center: [116.39, 39.9],zoom: 4,});reactiveUtils.whenOnce(() => view.popup.viewModel).then(() => {// Override the default symbol representing the cluster extentview.popup.viewModel.selectedClusterBoundaryFeature.symbol = {type: "simple-fill",style: "solid",color: "rgba(50,50,50,0.8)",outline: {width: 0.5,color: "rgba(50,50,50,0.8)",},};});const legend = new Legend({view,container: "legendDiv",});const infoDiv = document.getElementById("infoDiv");view.ui.add(new Expand({view,content: infoDiv,expandIcon: "list-bullet",expanded: true,}),"top-right",);layer.when().then(generateClusterConfig).then((featureReduction) => {layer.featureReduction = featureReduction;// 核心添加,切换点聚合模式,const toggleButton = document.getElementById("toggle-cluster");toggleButton.addEventListener("click", toggleClustering);// To turn off clustering on a layer, set the// featureReduction property to nullfunction toggleClustering() {let fr = layer.featureReduction;layer.featureReduction = fr && fr.type === "cluster" ? null : featureReduction;toggleButton.innerText =toggleButton.innerText === "启用聚合"? "禁用聚合": "启用聚合";}view.whenLayerView(layer).then((layerView) => {const filterSelect = document.getElementById("filter");filterSelect.addEventListener("change", (event) => {const newValue = event.target.value;const whereClause = newValue ? `category = ${newValue}` : null;console.log(whereClause)layerView.filter = {where: whereClause,};view.closePopup();});});}).catch((error) => {console.error(error);});async function generateClusterConfig(layer) {// generates default popupTemplateconst popupTemplate = await clusterPopupCreator.getTemplates({ layer }).then((popupTemplateResponse) => popupTemplateResponse.primaryTemplate.value);// generates default labelingInfoconst { labelingInfo, clusterMinSize } = await clusterLabelCreator.getLabelSchemes({ layer, view }).then((labelSchemes) => labelSchemes.primaryScheme);return {type: "cluster",popupTemplate,labelingInfo,clusterMinSize,maxScale: 50000};}function generateRandomPoints(count) {const points = [];for (let i = 0; i < count; i++) {const lon = (Math.random() * 119); // 经度范围const lat = (Math.random() * 30) + 30;  // 纬度范围// 随机分配类别const category = Math.floor(Math.random() * 4);points.push({geometry: {type: "point",longitude: lon,latitude: lat},attributes: {ObjectID: i,category: category,value: Math.floor(Math.random() * 100)}});}return points;}</script>
</head><body><div id="viewDiv"></div><div id="infoDiv" class="esri-widget">类别筛选(category):<select id="filter" class="esri-select"><option value="">全部</option><option value="1">类别1</option><option value="2">类别2</option><option value="3">类别3</option><option value="4">类别4</option></select><div style="padding-top: 10px"><button id="toggle-cluster" class="esri-button">点聚合</button></div><div id="legendDiv"></div></div>
</body></html>

tiandituLoader.js


/*** 天地图加载公共模块* 功能:封装天地图底图加载逻辑,返回配置好的Basemap实例* 依赖:ArcGIS API 4.x*/
export async function loadTiandituBasemap() {try {// 1. 按需导入ArcGIS核心模块const [WebTileLayer,Basemap,TileInfo] = await $arcgis.import(["@arcgis/core/layers/WebTileLayer","@arcgis/core/Basemap","@arcgis/core/layers/support/TileInfo",]);// 2. 配置参数(可根据需求调整)const config = {tk: "你的密钥", // 天地图密钥spatialReference: { wkid: 4326 },       // 目标坐标系(WGS84)subDomains: ["0", "1", "2", "3", "4", "5", "6", "7"], // 多子域名tileMatrixSet: "c",                     // 天地图瓦片矩阵集layerType: {vec: "vec", // 矢量底图cva: "cva"  // 矢量注记}};// 3. 定义瓦片信息(匹配WGS84坐标系的瓦片规则)const tileInfo = new TileInfo({dpi: 90.71428571427429,rows: 256,cols: 256,compressionQuality: 0,origin: { x: -180, y: 90 },spatialReference: config.spatialReference,lods: [{ level: 2, levelValue: 2, resolution: 0.3515625, scale: 147748796.52937502 },{ level: 3, levelValue: 3, resolution: 0.17578125, scale: 73874398.264687508 },{ level: 4, levelValue: 4, resolution: 0.087890625, scale: 36937199.132343754 },{ level: 5, levelValue: 5, resolution: 0.0439453125, scale: 18468599.566171877 },{ level: 6, levelValue: 6, resolution: 0.02197265625, scale: 9234299.7830859385 },{ level: 7, levelValue: 7, resolution: 0.010986328125, scale: 4617149.8915429693 },{ level: 8, levelValue: 8, resolution: 0.0054931640625, scale: 2308574.9457714846 },{ level: 9, levelValue: 9, resolution: 0.00274658203125, scale: 1154287.4728857423 },{ level: 10, levelValue: 10, resolution: 0.001373291015625, scale: 577143.73644287116 },{ level: 11, levelValue: 11, resolution: 0.0006866455078125, scale: 288571.86822143558 },{ level: 12, levelValue: 12, resolution: 0.00034332275390625, scale: 144285.93411071779 },{ level: 13, levelValue: 13, resolution: 0.000171661376953125, scale: 72142.967055358895 },{ level: 14, levelValue: 14, resolution: 8.58306884765625e-005, scale: 36071.483527679447 },{ level: 15, levelValue: 15, resolution: 4.291534423828125e-005, scale: 18035.741763839724 },{ level: 16, levelValue: 16, resolution: 2.1457672119140625e-005, scale: 9017.8708819198619 },{ level: 17, levelValue: 17, resolution: 1.0728836059570313e-005, scale: 4508.9354409599309 },{ level: 18, levelValue: 18, resolution: 5.3644180297851563e-006, scale: 2254.4677204799655 },{ level: 19, levelValue: 19, resolution: 2.68220901489257815e-006, scale: 1127.23386023998275 },{ level: 20, levelValue: 20, resolution: 1.341104507446289075e-006, scale: 563.616930119991375 }]});// 4. 构建天地图URL模板(支持多子域名)const getUrlTemplate = (layer) => {return `http://t0.tianditu.gov.cn/${layer}_${config.tileMatrixSet}/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=${layer}&STYLE=default&TILEMATRIXSET=${config.tileMatrixSet}&TILEMATRIX={level}&TILEROW={row}&TILECOL={col}&FORMAT=tiles&tk=${config.tk}`;};// 5. 创建矢量底图图层const vecLayer = new WebTileLayer({urlTemplate: getUrlTemplate(config.layerType.vec),subDomains: config.subDomains,copyright: "天地图 © 国家地理信息公共服务平台",spatialReference: config.spatialReference,tileInfo: tileInfo});// 6. 创建矢量注记图层const cvaLayer = new WebTileLayer({urlTemplate: getUrlTemplate(config.layerType.cva),subDomains: config.subDomains,copyright: "天地图 © 国家地理信息公共服务平台",spatialReference: config.spatialReference,tileInfo: tileInfo});// 7. 创建自定义底图并返回const tiandituBasemap = new Basemap({baseLayers: [vecLayer],referenceLayers: [cvaLayer],title: "天地图矢量图(WGS84)",id: "tianditu-vector-wgs84"});return {tileInfo,config,getUrlTemplate,tiandituBasemap,WebTileLayer,Basemap};} catch (error) {console.error("天地图加载失败:", error);throw new Error("天地图公共模块加载异常,请检查依赖和配置");}
}
http://www.dtcms.com/a/398808.html

相关文章:

  • Express使用教程(二)
  • 大模型部署基础设施搭建 - Docker
  • 芜湖建设机械网站企业管理系统软件下载
  • 永嘉县住房和城乡规划建设局网站自助贸易网
  • 华为云学习笔记(1):ECS 实例操作与密钥登录实践
  • 有一次django开发实录
  • RISC-V 中的 Wait For Interrupt 指令 (wfi) 详解
  • 前端核心框架vue之(指令案例篇1/5)
  • 企业静态网站源码增城建设局网站
  • 网站兼容9公司logo和商标一样吗
  • 题解:AT_abc206_e [ABC206E] Divide Both
  • 链改2.0总架构师何超秘书长重构“可信资产lPO与数链金融RWA”
  • 网站开发技术包括网站建设专业培训
  • 无人机航拍WiFi图传模块,16公里实时高清图传性能和技术参数
  • 视频元素在富文本编辑器中的光标问题
  • 企业网站内容如何搭建推荐做木工的视频网站
  • grounding dino 源码部署 cuda12.4 开放词汇目标检测(Open-Vocabulary Object Detection, OVOD)模型
  • 一个虚拟主机可以做几个网站吗毕设做网站心得体验
  • Spring使用SseEmitter实现后端流式传输和前端Vue数据接收
  • 湖南省新闻最新消息十条深圳seo网站推广方案
  • 语音交互接待服务机器人深度推荐
  • 创建学校网站吗网站搭建工具的种类
  • Linux-ARM-裸机开发-开发环境搭建
  • 2025年校园招聘平台怎么选?
  • 如何把视频放到自己的网站ftp怎么重新上传网站
  • minio文件迁移
  • 网站反链接是什么意思wordpress 侧边收起
  • docker-desktop 分发版不支持用户数据挂载
  • 部署LVS NAT集群
  • 使用 feature_engine库 提升你的机器学习特征工程效率