【2025最新】ArcGIS for JS 范围裁剪(只保留特定区域显示),实现精准地理范围聚焦
ArcGIS for JS 实战:范围裁剪(只保留特定区域显示),实现精准地理范围聚焦 🗺️
在 ArcGIS for JavaScript 开发中,经常会遇到 “只显示指定区域,隐藏其他范围” 的需求,比如区域数据可视化、特定地理范围分析等场景。本文适用于 ArcGIS Maps SDK for JavaScri pt 4.28~4.33 版本,结合天地图底图,带大家一步步实现 “特定区域保留显示” 功能,代码可直接复用!
文章目录
- ArcGIS for JS 实战:范围裁剪(只保留特定区域显示),实现精准地理范围聚焦 🗺️
- 效果图
- 一、核心思路:图层混合模式实现 “范围裁剪” ✂️
- 二、完整代码解析📝
- 1. 基础页面结构与样式
- 2. 核心模块引入与天地图加载
- 3. 定义 “保留区域” 的地理范围 📍
- 4. 构建 “裁剪层”:关键的 GraphicsLayer 🎨
- 5. 组合图层并初始化地图 🚀
- 三、关键注意事项 ⚠️
- 四、所有代码 🚀
- index.html
工具 /插件/系统 名 | 版本 | 说明 |
---|---|---|
ArcGIS JS API | 4.28~4.33 | 地图核心能力(底图加载、视图渲染) |
天地图服务 | - | 提供街道、卫星、地形等底图数据源 |
效果图
一、核心思路:图层混合模式实现 “范围裁剪” ✂️
实现 “只保留特定区域” 的核心原理是利用 GraphicsLayer
** 的 blendMode: "destination-in"
属性**:
-
destination-in
表示 “只显示当前图层与下层图层重叠的区域”,非重叠区域会被透明化 -
我们只需绘制一个 “目标保留区域” 的面图形,结合该混合模式,就能实现 “裁剪” 效果
-
搭配天地图底图,可快速构建带区域聚焦的地图应用
二、完整代码解析📝
1. 基础页面结构与样式
首先搭建 HTML 骨架,设置地图容器占满全屏,确保地图显示无偏差:
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><!-- 适配移动端,防止地图缩放异常 --><meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /><title>ArcGIS for JS 只保留特定区域</title><style>/* 地图容器全屏样式 */html, body, #viewDiv {padding: 0;margin: 0;height: 100%;width: 100%;}</style><!-- 引入ArcGIS核心样式和JS库 --><link rel="stylesheet" href="https://js.arcgis.com/4.33/esri/themes/light/main.css" /><script src="https://js.arcgis.com/4.33/"></script></head><body><!-- 地图渲染容器 --><div id="viewDiv"></div><script type="module">// 核心逻辑代码在这里...</script></body></html>
2. 核心模块引入与天地图加载
通过 $arcgis.import
引入 ArcGIS 核心模块,同时加载天地图底图(需提前准备 tiandituLoader.js
工具类,也可以直接在《天地图底图加载》)中直接复制。
// 1. 引入ArcGIS核心模块const [Map, MapView, GraphicsLayer, GroupLayer] =await $arcgis.import(["@arcgis/core/Map.js", // 地图实例"@arcgis/core/views/MapView.js", // 地图视图"@arcgis/core/layers/GraphicsLayer.js", // 矢量图形层"@arcgis/core/layers/GroupLayer.js" // 图层组(用于管理多个图层)]);// 2. 加载天地图底图(矢量图+注记层)import { loadTiandituBasemap } from './js/tiandituLoader.js';const {vecLayer: worldImagery, // 天地图矢量底图cvaLayer: tileLayer // 天地图注记层(显示地名)} = await loadTiandituBasemap();
3. 定义 “保留区域” 的地理范围 📍
通过 rings
数组定义多边形坐标(支持多环,可用于包含 “飞地” 场景),坐标格式为 [经度, 纬度]
, spatialReference 设为 4326
(WGS84 坐标系):
// 定义保留区域的多边形坐标(示例为两个闭合区域)const rings = [// 第一个区域(示例范围)[[123.09306581, 43.90257375], [123.82517908, 43.58244008], [124.26830027, 42.49823921], [120.41507254, 41.97045084], [120.33800799, 43.61034574], [123.09306581, 43.90257375]], // 闭合坐标(首尾一致)// 第二个区域(可理解为“飞地”)[[124.52760067, 45.86828802], [121.05156665, 44.74454778], [125.90119475, 44.46513338], [124.52760067, 45.86828802]]];
4. 构建 “裁剪层”:关键的 GraphicsLayer 🎨
创建 GraphicsLayer
并设置 blendMode: "destination-in"
,这是实现 “只保留特定区域” 的核心步骤:
const graphicsLayer = new GraphicsLayer({blendMode: "destination-in", // 核心混合模式:只显示重叠区域title: "特定保留区域",graphics: [new Graphic({geometry: {type: "polygon", // 图形类型:多边形rings: rings, // 绑定上面定义的区域坐标spatialReference: { wkid: 4326 } // 坐标系},symbol: { // 多边形样式(因混合模式,颜色仅影响重叠区域透明度)type: "simple-fill",color: [0, 0, 0, 1], // 黑色不透明(确保重叠区域完全显示)outline: { // 区域边界样式color: [255, 0, 0], // 红色边界width: 2 // 边界宽度}},})]});
5. 组合图层并初始化地图 🚀
将天地图底图、注记层、裁剪层组合成 GroupLayer
,避免图层层级混乱,最后初始化地图视图:
// 1. 组合图层(顺序:底图 → 注记 → 裁剪层)const groupLayer = new GroupLayer({layers: [worldImagery, tileLayer, graphicsLayer],opacity: 1 // 整体图层透明度});// 2. 创建地图实例const map = new Map({layers: [groupLayer] // 绑定图层组});// 3. 创建地图视图(控制地图显示)const view = new MapView({container: "viewDiv", // 绑定地图容器map: map, // 绑定地图实例center: [125.8425456, 43.85312804], // 初始中心点坐标zoom: 8, // 初始缩放级别(根据区域大小调整)constraints: {minScale: 19499143, // 最小缩放级别(防止缩太小看到无关区域)maxScale: 5000 // 最大缩放级别(防止放太大模糊)},popup: null // 暂时关闭弹窗(如需启用,可删除此配置)});// 可选:地图加载完成后提示view.when(() => {console.log("地图加载完成,已显示特定保留区域!");});
三、关键注意事项 ⚠️
-
坐标顺序问题:ArcGIS 中
rings
坐标格式为[经度, 纬度]
,不要和[纬度, 经度]
混淆,否则区域会显示异常; -
混合模式生效条件:
GraphicsLayer
必须放在最上层(图层顺序:底图 → 业务层 → 裁剪层),否则混合模式不生效; -
天地图加载依赖:
tiandituLoader.js
需要正确配置天地图 Key(需自行申请天地图开发者账号,免费版足够测试); -
多区域支持:
rings
数组支持多个子数组,可实现 “多个不连续区域同时保留”(如多个城市、多个地块)。
四、所有代码 🚀
index.html
<!DOCTYPE html>
<!doctype html>
<html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /><title>Highlight a country with an effect | Sample | ArcGIS Maps SDK for JavaScript 4.33</title><style>html,body,#viewDiv {padding: 0;margin: 0;height: 100%;width: 100%;}#messageDiv {padding-left: 10px;padding-right: 10px;}</style><link rel="stylesheet" href="https://js.arcgis.com/4.33/esri/themes/light/main.css" /><script src="https://js.arcgis.com/4.33/"></script><script type="module">const [Map, MapView, TileLayer, Graphic, GraphicsLayer, GroupLayer] =await $arcgis.import(["@arcgis/core/Map.js","@arcgis/core/views/MapView.js","@arcgis/core/layers/TileLayer.js","@arcgis/core/Graphic.js","@arcgis/core/layers/GraphicsLayer.js","@arcgis/core/layers/GroupLayer.js"]);import { loadTiandituBasemap } from './js/tiandituLoader.js';const {config,getUrlTemplate,WebTileLayer,vecLayer: worldImagery,cvaLayer: tileLayer,tileInfo } = await loadTiandituBasemap();const rings = [[[123.09306581, 43.90257375], [123.82517908, 43.58244008], [124.26830027, 42.49823921],[120.41507254, 41.97045084], [120.33800799, 43.61034574], [123.09306581, 43.90257375]],[[124.52760067, 45.86828802], [121.05156665, 44.74454778], [125.90119475, 44.46513338], [124.52760067, 45.86828802]]]const graphicsLayer = new GraphicsLayer({blendMode: "destination-in",title: "layer",graphics: [new Graphic({geometry: {type: "polygon",rings,spatialReference: { wkid: 4326 }},attributes: {objectid: 1,// name:,longitude: 116.397428,latitude: 39.90923},symbol: {type: "simple-fill",color: [0, 0, 0, 1],outline: {color: [0, 0, 0],width: 2}},}),],});const groupLayer = new GroupLayer({layers: [worldImagery,tileLayer,graphicsLayer,],opacity: 1,});const map = new Map({layers: [groupLayer]});const view = new MapView({container: "viewDiv",map: map,center: [125.8425456, 43.85312804], // 鍖椾含鍧愭爣popup: null,constraints: {minScale: 19499143,},});</script>
</head><body><div id="viewDiv"></div>
</body></html>