cc-arcgis-map
v1.0.13
Published
Vue 3 component for ArcGIS 3.x maps with full configuration support
Downloads
1,440
Maintainers
Readme
cc-arcgis-map
Vue 3 组件,用于 ArcGIS 3.x 地图的快速集成。支持完整的配置系统、MapUtil工具类以及灵活的扩展机制。
🏢 核心优势
🏢 企业级内网支持 - 开箱即用的内网ArcGIS配置,无需额外设置即可使用 📍 武汉2000坐标系 - 专门优化的本地坐标支持,默认可视范围已配置 🗺️ 50+预配置图层 - 涵盖电子地图、影像、专题图等所有常用图层 🛠️ 43个实用工具方法 - 涵盖绘制、查询、测量等所有地图操作场景
✨ 特性
- 🗺️ 完整的ArcGIS 3.x支持 - 基于esri-loader,完整支持ArcGIS 3.x API
- 🎨 零配置使用 - 开箱即用,包含完整的默认配置(50+图层、内网地址等)
- ⚙️ 灵活的全局配置 - 通过Vue插件一次性配置,所有组件自动使用
- 🛠️ 强大的MapUtil工具类 - 保留所有原有方法,支持扩展
- 📦 TypeScript支持 - 完整的类型定义和智能提示
- 🔧 Composable API - 提供useMap、useMapLayer等组合式API
- 🚀 性能优化 - 图层缓存、懒加载队列等优化机制
📦 安装
当前版本: v1.0.12
npm install [email protected] esri-loader
# 或
yarn add [email protected] esri-loader注意: 本组件库专为内网环境优化,默认已配置内网ArcGIS服务地址。如需外网使用,请参考下方配置章节。
🚀 快速开始
1. 全局注册(推荐)
在应用入口文件中注册插件:
// main.ts
import { createApp } from 'vue'
import VueArcgisMap from 'cc-arcgis-map'
import 'cc-arcgis-map/style.css'
import App from './App.vue'
const app = createApp(App)
// 方式1: 直接使用默认配置(包含所有预配置图层和内网设置)
app.use(VueArcgisMap)
// 方式2: 覆盖部分配置
app.use(VueArcgisMap, {
esriconfig: {
url: 'http://192.168.8.74:8085/arcgis_js_api/init.js'
},
mapExtent: {
xMin: 725836,
yMin: 355421,
xMax: 876728,
yMax: 423604
}
})
app.mount('#app')2. 在组件中使用
<template>
<!-- 基础使用 -->
<ArcgisMap
@map-ready="onMapReady"
@map-click="onMapClick"
/>
<!-- 带参数使用 -->
<ArcgisMap
:center="[114.3055, 30.5996]"
:zoom="13"
:base-layer="'暗黑版电子地图'"
@map-ready="onMapReady"
/>
</template>
<script setup lang="ts">
import type { MapReadyEvent, MapClickEvent } from 'cc-arcgis-map'
const onMapReady = (event: MapReadyEvent) => {
const { map, mapUtil } = event
// 使用MapUtil添加图形
mapUtil.addPointMark(map, 114.3, 30.5, '/icon.png', { id: '1', name: '标注点' })
mapUtil.addPolygonGraphic(map, [[
[114.3, 30.5],
[114.4, 30.5],
[114.4, 30.6],
[114.3, 30.6]
]], { id: '2', name: '地块' })
}
const onMapClick = (event: MapClickEvent) => {
console.log('点击坐标:', event.mapPoint)
}
</script>🔧 内网环境配置
默认内网配置
本组件库已内置内网环境的 ArcGIS 配置:
// 默认内网配置
{
esriconfig: {
url: 'http://192.168.8.74:8085/arcgis_js_api/init.js'
}
}修改内网地址
如需修改为其他内网地址:
app.use(VueArcgisMap, {
esriconfig: {
url: 'http://your-server:port/arcgis_js_api/init.js'
}
})外网环境配置
如需在外网环境使用,配置官方 ArcGIS API:
app.use(VueArcgisMap, {
esriconfig: {
url: 'https://js.arcgis.com/3.41/init.js'
}
})最佳实践
- 内网环境:使用默认配置即可,所有图层已配置内网地址
- 图层URL:所有预配置图层默认使用内网地址前缀
- 性能优化:内网环境下建议启用本地缓存以提升加载速度
📍 武汉2000坐标系
坐标系范围
默认配置了武汉2000坐标系的可视范围:
// 武汉2000坐标系默认范围
{
xMin: 725836,
yMin: 355421,
xMax: 876728,
yMax: 423604
}自定义范围
// 修改可视范围
app.use(VueArcgisMap, {
mapExtent: {
xMin: 700000,
yMin: 350000,
xMax: 900000,
yMax: 450000
}
})坐标转换示例
// 地理坐标(WGS84)转武汉2000
const wgs84Point = [114.3055, 30.5996]
const wh2000Point = coordinateTransform(wgs84Point, 'WGS84', 'WH2000')
// 在地图上添加点
mapUtil.addPointMark(map, wh2000Point[0], wh2000Point[1], icon, attrs)🗺️ 预配置图层列表
本组件库内置了50+个常用图层,按类型分为:
电子地图类
- 暗黑版电子地图 - 适合夜间使用
- 标准版电子地图 - 日常使用标准样式
- 影像版电子地图 - 卫星影像底图
- 注记版电子地图 - 带地名标注
专题地图类
- 行政区划 - 省、市、县级行政边界
- 地名地址 - 兴趣点、街道名称
- 水系分布 - 河流、湖泊、水库
- 道路网络 - 高速、国道、省道
业务图层类
可根据业务需求动态添加:
// 添加业务图层
addLayerConfig({
label: '业务图层',
mapUrl: 'http://your-server/arcgis/rest/services/ServiceName/MapServer',
mapType: 'dynamic',
visible: true
})📖 API文档
组件 Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| center | [number, number] | [114.3055, 30.5996] | 地图中心点 |
| zoom | number | 13 | 缩放级别 |
| extent | MapExtent | - | 地图范围 |
| baseLayer | string \| LayerConfig \| false | '暗黑版电子地图' | 底图配置 |
| layers | LayerConfig[] | [] | 额外图层 |
| showLoading | boolean | true | 是否显示加载状态 |
| esriConfig | Partial<EsriConfig> | - | 自定义ArcGIS配置 |
组件 Events
| 事件名 | 参数 | 说明 |
|--------|------|------|
| map-ready | { map, geometryEngine, mapUtil } | 地图加载完成 |
| map-click | MapClickEvent | 地图点击事件 |
| zoom-change | ZoomChangeEvent | 缩放级别变化 |
| center-change | CenterChangeEvent | 中心点变化 |
| extent-change | ExtentChangeEvent | 范围变化 |
组件方法
通过 ref 可以调用组件的公共方法:
<template>
<ArcgisMap ref="mapRef" />
</template>
<script setup lang="ts">
const mapRef = ref<InstanceType<typeof ArcgisMap>>()
const clearMap = () => {
mapRef.value?.clearGraphics()
}
const zoomToExtent = () => {
mapRef.value?.setExtent({
xMin: 725836,
yMin: 355421,
xMax: 876728,
yMax: 423604
})
}
</script>| 方法 | 说明 |
|------|------|
| getMap() | 获取地图实例 |
| getGeometryEngine() | 获取几何引擎 |
| getMapUtil() | 获取MapUtil实例 |
| clearGraphics() | 清除所有图形 |
| setExtent(extent, fit?) | 设置地图范围 |
| zoomToGraphics(graphics, expand?) | 缩放到图形 |
🛠️ MapUtil工具类
MapUtil 提供了43个实用的地图操作方法,完全向后兼容原有代码。
📍 图形绘制类(13个)
点标记
// 添加图片标记
mapUtil.addPointMark(map, x, y, imgPath, attributes)
// 添加圆形标记
mapUtil.addPointRound(map, x, y, rgba, radius, attributes)
// 添加文字标记
mapUtil.addPointFont(map, x, y, text, attributes)
// 添加文本标注
mapUtil.addPointText(map, x, y, text, textColor, attributes)线图形
// 添加线图形
mapUtil.addLineGraphic(map, paths, attributes)
// 添加渐变线
mapUtil.addLineRound(map, paths, attributes)
// 添加动态线(带流向)
mapUtil.addLineDynamic(map, paths, attributes)面图形
// 添加面图形
mapUtil.addPolygonGraphic(map, rings, attributes)
// 添加渐变面
mapUtil.addPolygonGradient(map, rings, attributes)
// 添加动态面
mapUtil.addPolygonDynamic(map, rings, attributes)其他图形
// 添加圆
mapUtil.addCircleGraphic(map, center, radius, attributes)
// 添加环形
mapUtil.addDonutGraphic(map, rings, attributes)
// 添加图片
mapUtil.addImageGraphic(map, extent, imageUrl, attributes)🗂️ 图层管理类(8个)
// 控制图层显隐
mapUtil.controlLayer(map, layerConfig, visible)
// 添加图层到列表
mapUtil.addMenuLayer(map, url, type, id, alpha)
// 添加WFS图层
mapUtil.addWFSLayer(map, url, layerName)
// 移除WFS图层
mapUtil.removeWFSLayer(map, layerName)
// 创建矢量图层
mapUtil.createVectorLayer(map, layerId)
// 根据名称获取图层
mapUtil.getLayerByName(map, layerName)
// 根据标题获取图层
mapUtil.getLayerByTitle(map, title)
// 获取所有图层信息
mapUtil.getAllLayerInfos(map)🔍 空间查询类(8个)
// 通用查询
mapUtil.query(url, where, outFields, callback)
// 条件查询
mapUtil.queryByWhere(url, where, outFields, callback)
// 几何查询
mapUtil.queryByGeometry(url, geometry, spatialRelationship, callback)
// 要素查找
mapUtil.findTask(url, searchFields, searchText, callback)
// 要素识别
mapUtil.identinate(url, geometry, tolerance, callback)
// 空间关系查询
mapUtil.spatialQuery(url, geometry, spatialRelationship, callback)
// 获取图层字段
mapUtil.getLayerFields(url, callback)
// 统计分析
mapUtil.getStatistics(url, field, statisticType, callback)📐 几何操作类(7个)
// 获取几何中心
mapUtil.getGeometryCenter(geometry)
// 获取总范围
mapUtil.getTotalExtent(geometryList, spatialReference)
// 缓冲区分析
mapUtil.geometryBuffer(geometry, distance)
// 相交分析
mapUtil.intersect(geometry1, geometry2)
// 合并分析
mapUtil.union(geometryList)
// 计算面积
mapUtil.getArea(geometry)
// 计算长度
mapUtil.getLength(geometry)🛠️ 实用工具类(7个)
// 清除所有图形
mapUtil.clearAllGraphic(map)
// 清除指定图形
mapUtil.clearTargetGraphics(map, attributeName, attributeValue)
// 图形闪烁
mapUtil.geometryFlick(map, geometry, attributes, isLoop)
// 开始绘制
mapUtil.startDraw(map, drawType, callback)
// 停止绘制
mapUtil.stopDraw(map)
// 距离测量
mapUtil.measureDistance(map, callback)
// 面积测量
mapUtil.measureArea(map, callback)扩展方法
// 注册单方法
mapUtil.extend('addHeatMap', function(data, options) {
// this 指向 mapUtil 实例
const map = this.getMap()
// 实现热力图逻辑...
})
// 批量注册
mapUtil.use({
addCluster(points) {
// 聚合图实现
},
addTrack(coordinates) {
// 轨迹图实现
}
})
// 使用扩展方法
mapUtil.addHeatMap(data, options)🎨 Composables API
useMap - 地图基础操作
import { useMap } from 'cc-arcgis-map'
const { map, setExtent, setCenter, setZoom } = useMap()
setExtent({ xMin: 1, yMin: 2, xMax: 3, yMax: 4 })
setCenter([114, 30], 13)useMapLayer - 图层管理
import { useMapLayer } from 'cc-arcgis-map'
const { addLayer, removeLayer, toggleLayer } = useMapLayer(map)
addLayer({
label: '自定义图层',
mapUrl: 'http://example.com/map',
mapType: 'dynamic'
})useMapGraphics - 图形操作
import { useMapGraphics } from 'cc-arcgis-map'
const { addPointMark, addPolygon, clearAll } = useMapGraphics(map)
addPointMark(114, 30, '/icon.png', { id: '1' })
addPolygon([[[114, 30], [115, 30], [115, 31], [114, 31]]], { id: '2' })useMapQuery - 空间查询
import { useMapQuery } from 'cc-arcgis-map'
const { queryByWhere, spatialQuery } = useMapQuery(map)
queryByWhere(
'http://example.com/map/MapServer/0',
"NAME = '武汉'",
['*'],
true,
(result) => {
console.log('查询结果:', result)
}
)⚙️ 配置系统
默认配置
包内置了完整的默认配置:
- esriconfig: 内网ArcGIS地址
- mapExtent: 武汉2000坐标系范围
- layerConfig: 50+个完整图层配置
- defaultBaseLayer: '暗黑版电子地图'
覆盖配置
app.use(VueArcgisMap, {
esriconfig: {
url: 'http://192.168.8.74:8085/arcgis_js_api/init.js'
},
mapExtent: {
xMin: 725836,
yMin: 355421,
xMax: 876728,
yMax: 423604
},
layerConfig: [
...getDefaultLayerConfig(), // 保留所有默认图层
{ label: '新图层', mapUrl: '...', mapType: 'dynamic' }
]
})运行时配置
import { addLayerConfig, updateLayerConfig } from 'cc-arcgis-map'
// 添加新图层
addLayerConfig({
label: '运行时添加的图层',
mapUrl: 'http://example.com/map',
mapType: 'dynamic'
})
// 更新现有图层
updateLayerConfig('电子地图', {
mapUrl: 'http://new-server.com/map'
})🔄 从现有项目迁移
现有代码
// 旧代码
import { mapUtil } from '@/utils/MapUtil'
// 使用
mapUtil.addPointMark(map, x, y, icon, attrs)迁移后
// 新代码(完全兼容)
import { mapUtil } from 'cc-arcgis-map'
// mapUtil方法调用完全不变
mapUtil.addPointMark(map, x, y, icon, attrs)获取配置
如果之前使用了 sysConfig,现在可以用 getGlobalConfig 获取:
import { getGlobalConfig } from 'cc-arcgis-map'
// 获取所有配置
const config = getGlobalConfig()
console.log(config.layerConfig) // 所有图层配置
console.log(config.esriconfig) // ArcGIS配置💡 实战示例
基础使用示例
最简单的地图初始化
<template>
<div class="map-container">
<ArcgisMap
@map-ready="onMapReady"
style="width: 100%; height: 500px;"
/>
</div>
</template>
<script setup lang="ts">
import { ArcgisMap } from 'cc-arcgis-map'
const onMapReady = (event: MapReadyEvent) => {
console.log('地图加载完成', event.map)
}
</script>添加点标记和响应点击
<template>
<ArcgisMap
:center="[114.3055, 30.5996]"
:zoom="13"
@map-ready="onMapReady"
@map-click="onMapClick"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { MapReadyEvent, MapClickEvent } from 'cc-arcgis-map'
const mapInstance = ref<any>()
const onMapReady = (event: MapReadyEvent) => {
const { map, mapUtil } = event
mapInstance.value = map
// 添加一个标记点
mapUtil.addPointMark(
map,
114.3055,
30.5996,
'/location-pin.png',
{ id: 'hq', name: '总部', type: 'important' }
)
}
const onMapClick = (event: MapClickEvent) => {
console.log('点击位置:', event.mapPoint)
// 在点击位置添加临时标记
if (mapInstance.value) {
mapUtil.addPointRound(
mapInstance.value,
event.mapPoint.x,
event.mapPoint.y,
'rgba(255, 0, 0, 0.8)',
8,
{ temp: true }
)
}
}
</script>高级功能示例
复杂空间查询
<template>
<div>
<ArcgisMap ref="mapRef" @map-ready="onMapReady" />
<div class="toolbar">
<button @click="queryNearby">查询周边1公里</button>
<button @click="queryByGeometry">查询选中区域</button>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useMapQuery } from 'cc-arcgis-map'
const mapRef = ref()
const mapInstance = ref()
const { queryByWhere, spatialQuery } = useMapQuery(mapInstance)
const onMapReady = (event: MapReadyEvent) => {
mapInstance.value = event.map
}
// 查询周边1公里的POI
const queryNearby = () => {
const center = [114.3055, 30.5996] // 武汉市中心
const radius = 1000 // 1公里
// 创建缓冲区
const buffer = mapUtil.geometryBuffer(
{ x: center[0], y: center[1] },
radius
)
spatialQuery(
'http://your-server/arcgis/rest/services/POI/MapServer/0',
buffer,
'INTERSECT',
['*'],
(result) => {
console.log('找到', result.features.length, '个POI')
// 在地图上显示结果
result.features.forEach(feature => {
mapUtil.addPointMark(
mapInstance.value,
feature.geometry.x,
feature.geometry.y,
'/poi-icon.png',
feature.attributes
)
})
}
)
}
// 查询用户绘制的区域
const queryByGeometry = () => {
// 开始绘制多边形
mapUtil.startDraw(mapInstance.value, 'POLYGON', (geometry) => {
queryByWhere(
'http://your-server/arcgis/rest/services/LandUse/MapServer/0',
`LAND_TYPE = '商业用地'`,
['*'],
true,
(result) => {
console.log('商业用地查询结果:', result)
}
)
})
}
</script>图层动态切换和透明度控制
<template>
<div>
<ArcgisMap :base-layer="currentBaseLayer" @map-ready="onMapReady" />
<div class="layer-control">
<h3>底图切换</h3>
<button
v-for="layer in baseLayers"
:key="layer.label"
@click="switchBaseLayer(layer)"
:class="{ active: currentBaseLayer === layer.label }"
>
{{ layer.label }}
</button>
<h3>图层控制</h3>
<div v-for="layer in overlayLayers" :key="layer.id">
<label>
<input
type="checkbox"
v-model="layer.visible"
@change="toggleLayer(layer)"
/>
{{ layer.label }}
</label>
<input
type="range"
min="0"
max="100"
v-model="layer.opacity"
@input="setLayerOpacity(layer)"
/>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { useMapLayer, getGlobalConfig } from 'cc-arcgis-map'
const mapInstance = ref()
const { addLayer, removeLayer, toggleLayer, setOpacity } = useMapLayer(mapInstance)
const config = getGlobalConfig()
const currentBaseLayer = ref('暗黑版电子地图')
const baseLayers = config.layerConfig.filter(layer =>
layer.label.includes('电子地图') || layer.label.includes('影像')
)
const overlayLayers = reactive([
{
id: 'road',
label: '道路网络',
visible: true,
opacity: 100,
config: config.layerConfig.find(l => l.label === '道路网络')
},
{
id: 'poi',
label: '兴趣点',
visible: false,
opacity: 80,
config: config.layerConfig.find(l => l.label === '地名地址')
}
])
const onMapReady = (event: MapReadyEvent) => {
mapInstance.value = event.map
// 添加叠加图层
overlayLayers.forEach(layer => {
if (layer.visible && layer.config) {
addLayer(layer.config)
}
})
}
const switchBaseLayer = (layer: any) => {
currentBaseLayer.value = layer.label
// 组件会自动响应 base-layer prop 的变化
}
const toggleLayer = (layer: any) => {
if (layer.config) {
if (layer.visible) {
addLayer(layer.config)
} else {
removeLayer(layer.config)
}
}
}
const setLayerOpacity = (layer: any) => {
if (layer.config) {
setOpacity(layer.config, layer.opacity / 100)
}
}
</script>
<style scoped>
.layer-control {
position: absolute;
top: 10px;
right: 10px;
background: white;
padding: 15px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}
.active {
background-color: #007cff;
color: white;
}
</style>完整项目示例
综合地图应用(包含工具栏、图层控制、查询、测量)
<template>
<div class="map-app">
<!-- 顶部工具栏 -->
<div class="toolbar">
<button @click="zoomIn">放大</button>
<button @click="zoomOut">缩小</button>
<button @click="toggleMeasure">
{{ measuring ? '停止测量' : '距离测量' }}
</button>
<button @click="clearAll">清除所有</button>
<button @click="toggleLayerPanel">
{{ showLayerPanel ? '隐藏图层' : '显示图层' }}
</button>
</div>
<!-- 地图容器 -->
<div class="map-wrapper">
<ArcgisMap
ref="mapRef"
:center="center"
:zoom="zoom"
@map-ready="onMapReady"
@map-click="onMapClick"
/>
<!-- 图层面板 -->
<div v-if="showLayerPanel" class="layer-panel">
<h3>图层控制</h3>
<div class="layer-group" v-for="group in layerGroups" :key="group.name">
<h4>{{ group.name }}</h4>
<label v-for="layer in group.layers" :key="layer.id">
<input
type="checkbox"
:checked="layer.visible"
@change="toggleLayerVisibility(layer)"
/>
{{ layer.label }}
</label>
</div>
</div>
<!-- 查询结果面板 -->
<div v-if="queryResults.length > 0" class="result-panel">
<h3>查询结果 ({{ queryResults.length }})</h3>
<ul>
<li v-for="item in queryResults" :key="item.id">
{{ item.name }} - {{ item.address }}
<button @click="locateFeature(item)">定位</button>
</li>
</ul>
</div>
<!-- 坐标显示 -->
<div class="coord-display">
坐标: {{ coords.x.toFixed(6) }}, {{ coords.y.toFixed(6) }}
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import {
ArcgisMap,
useMap,
useMapLayer,
useMapGraphics,
useMapQuery,
mapUtil,
getGlobalConfig
} from 'cc-arcgis-map'
import type { MapReadyEvent, MapClickEvent } from 'cc-arcgis-map'
// 响应式数据
const mapRef = ref()
const mapInstance = ref()
const measuring = ref(false)
const showLayerPanel = ref(false)
const queryResults = ref([])
const coords = reactive({ x: 0, y: 0 })
const center = ref([114.3055, 30.5996])
const zoom = ref(13)
// 获取配置
const config = getGlobalConfig()
const { setZoom, zoomToGraphics } = useMap(mapInstance)
const { addLayer, removeLayer, toggleLayer } = useMapLayer(mapInstance)
const { addPointMark, addPolygon, clearAllGraphics } = useMapGraphics(mapInstance)
const { queryByWhere, spatialQuery } = useMapQuery(mapInstance)
// 图层分组
const layerGroups = [
{
name: '基础地图',
layers: [
{ id: 'base-dark', label: '暗黑版', type: 'base', visible: true },
{ id: 'base-standard', label: '标准版', type: 'base', visible: false },
{ id: 'base-image', label: '影像版', type: 'base', visible: false }
]
},
{
name: '业务图层',
layers: [
{ id: 'boundary', label: '行政区划', type: 'overlay', visible: true },
{ id: 'poi', label: '兴趣点', type: 'overlay', visible: false },
{ id: 'traffic', label: '交通路网', type: 'overlay', visible: true }
]
}
]
// 地图就绪
const onMapReady = (event: MapReadyEvent) => {
mapInstance.value = event.map
// 添加默认图层
layerGroups.forEach(group => {
group.layers.forEach(layer => {
if (layer.visible) {
const layerConfig = config.layerConfig.find(l =>
l.label.includes(layer.label)
)
if (layerConfig) {
addLayer(layerConfig)
}
}
})
})
// 添加欢迎标记
mapUtil.addPointMark(
event.map,
center.value[0],
center.value[1],
'/welcome.png',
{ name: '欢迎使用cc-arcgis-map', type: 'welcome' }
)
}
// 地图点击
const onMapClick = (event: MapClickEvent) => {
coords.x = event.mapPoint.x
coords.y = event.mapPoint.y
if (measuring.value) {
// 测量模式:添加测量点
mapUtil.addPointRound(
event.map,
event.mapPoint.x,
event.mapPoint.y,
'rgba(255, 0, 0, 0.8)',
5,
{ measure: true }
)
}
}
// 工具栏功能
const zoomIn = () => {
setZoom(zoom.value + 1)
}
const zoomOut = () => {
setZoom(zoom.value - 1)
}
const toggleMeasure = () => {
measuring.value = !measuring.value
if (measuring.value) {
mapUtil.measureDistance(mapInstance.value, (result) => {
console.log('测量结果:', result.distance, '米')
})
} else {
mapUtil.stopDraw(mapInstance.value)
}
}
const clearAll = () => {
clearAllGraphics()
queryResults.value = []
}
const toggleLayerPanel = () => {
showLayerPanel.value = !showLayerPanel.value
}
// 图层控制
const toggleLayerVisibility = (layer: any) => {
layer.visible = !layer.visible
const layerConfig = config.layerConfig.find(l =>
l.label.includes(layer.label)
)
if (layerConfig) {
if (layer.visible) {
addLayer(layerConfig)
} else {
removeLayer(layerConfig)
}
}
}
// 查询功能示例
const searchPOI = (keyword: string) => {
queryByWhere(
'http://your-server/arcgis/rest/services/POI/MapServer/0',
`NAME LIKE '%${keyword}%'`,
['*'],
true,
(result) => {
queryResults.value = result.features.map(feature => ({
id: feature.attributes.OBJECTID,
name: feature.attributes.NAME,
address: feature.attributes.ADDRESS,
geometry: feature.geometry
}))
// 在地图上显示结果
result.features.forEach(feature => {
addPointMark(
feature.geometry.x,
feature.geometry.y,
'/search-result.png',
feature.attributes
)
})
}
)
}
// 定位要素
const locateFeature = (item: any) => {
// 缩放到要素
zoomToGraphics([{
geometry: { x: item.x, y: item.y }
}])
// 添加闪烁效果
mapUtil.geometryFlick(
mapInstance.value,
{ x: item.x, y: item.y },
{ name: item.name },
false
)
}
// 初始化
onMounted(() => {
// 可以在这里添加初始化逻辑
})
</script>
<style scoped>
.map-app {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
}
.toolbar {
height: 50px;
background: #333;
display: flex;
align-items: center;
padding: 0 20px;
gap: 10px;
}
.toolbar button {
padding: 8px 16px;
background: #007cff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.toolbar button:hover {
background: #0056b3;
}
.map-wrapper {
flex: 1;
position: relative;
}
.layer-panel, .result-panel {
position: absolute;
top: 10px;
right: 10px;
background: white;
padding: 15px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
max-height: 400px;
overflow-y: auto;
z-index: 1000;
}
.result-panel {
top: auto;
bottom: 10px;
max-height: 200px;
}
.layer-group {
margin-bottom: 15px;
}
.coord-display {
position: absolute;
bottom: 10px;
left: 10px;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 5px 10px;
border-radius: 3px;
font-size: 12px;
}
</style>📝 TypeScript支持
完整支持TypeScript类型定义:
import type {
ArcgisMapProps,
ArcgisMapEmits,
MapReadyEvent,
MapClickEvent,
LayerConfig,
EsriConfig
} from 'cc-arcgis-map'
const props = defineProps<ArcgisMapProps>()
const emit = defineEmits<ArcgisMapEmits>()
const onReady = (event: MapReadyEvent) => {
const { map, mapUtil } = event
}🤝 贡献
欢迎提交 Issue 和 Pull Request!
📄 许可证
MIT
🙏 致谢
- 基于 Vue 3 Composition API
- 使用 esri-loader 加载 ArcGIS API
- 参考 ArcGIS JavaScript API 3.x
