|
@@ -1,6 +1,6 @@
|
|
|
<template>
|
|
<template>
|
|
|
<div class="map-container">
|
|
<div class="map-container">
|
|
|
- <div ref="mapNodeRef" class="map-node" />
|
|
|
|
|
|
|
+ <div ref="mapNodeRef" class="map-node"/>
|
|
|
|
|
|
|
|
<!-- 底图切换 -->
|
|
<!-- 底图切换 -->
|
|
|
<div class="basemap-panel" v-show="showBasemapMenu">
|
|
<div class="basemap-panel" v-show="showBasemapMenu">
|
|
@@ -13,12 +13,16 @@
|
|
|
|
|
|
|
|
<!-- 图层按钮 -->
|
|
<!-- 图层按钮 -->
|
|
|
<div class="layer-btn" @click="showBasemapMenu = !showBasemapMenu" title="图层切换">
|
|
<div class="layer-btn" @click="showBasemapMenu = !showBasemapMenu" title="图层切换">
|
|
|
- <el-icon :size="22"><Operation /></el-icon>
|
|
|
|
|
|
|
+ <el-icon :size="22">
|
|
|
|
|
+ <Operation/>
|
|
|
|
|
+ </el-icon>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- 全图 -->
|
|
<!-- 全图 -->
|
|
|
<div class="full-extent-btn" @click="zoomToFull" title="全图">
|
|
<div class="full-extent-btn" @click="zoomToFull" title="全图">
|
|
|
- <el-icon :size="22"><FullScreen /></el-icon>
|
|
|
|
|
|
|
+ <el-icon :size="22">
|
|
|
|
|
+ <FullScreen/>
|
|
|
|
|
+ </el-icon>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- 经纬度 -->
|
|
<!-- 经纬度 -->
|
|
@@ -29,17 +33,15 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
-import { ref, onMounted, onUnmounted, shallowRef } from 'vue'
|
|
|
|
|
|
|
+import {onMounted, onUnmounted, ref, shallowRef} from 'vue'
|
|
|
import MapView from '@arcgis/core/views/MapView'
|
|
import MapView from '@arcgis/core/views/MapView'
|
|
|
import Map from '@arcgis/core/Map'
|
|
import Map from '@arcgis/core/Map'
|
|
|
import WebTileLayer from '@arcgis/core/layers/WebTileLayer'
|
|
import WebTileLayer from '@arcgis/core/layers/WebTileLayer'
|
|
|
-import TileLayer from '@arcgis/core/layers/TileLayer'
|
|
|
|
|
import MapImageLayer from '@arcgis/core/layers/MapImageLayer'
|
|
import MapImageLayer from '@arcgis/core/layers/MapImageLayer'
|
|
|
import Extent from '@arcgis/core/geometry/Extent'
|
|
import Extent from '@arcgis/core/geometry/Extent'
|
|
|
import SpatialReference from '@arcgis/core/geometry/SpatialReference'
|
|
import SpatialReference from '@arcgis/core/geometry/SpatialReference'
|
|
|
-import Graphic from '@arcgis/core/Graphic'
|
|
|
|
|
import FeatureLayer from '@arcgis/core/layers/FeatureLayer'
|
|
import FeatureLayer from '@arcgis/core/layers/FeatureLayer'
|
|
|
-import { basemapGroups, taihuServiceLayers } from './config/layers'
|
|
|
|
|
|
|
+import {basemapGroups, taihuServiceLayers} from './config/layers'
|
|
|
|
|
|
|
|
const emit = defineEmits(['mapReady', 'mapClick'])
|
|
const emit = defineEmits(['mapReady', 'mapClick'])
|
|
|
|
|
|
|
@@ -56,7 +58,7 @@ const layerGroups = shallowRef({})
|
|
|
// 太湖流域范围 [119.92, 31.17], WGS84 (wkid 4490)
|
|
// 太湖流域范围 [119.92, 31.17], WGS84 (wkid 4490)
|
|
|
const taihuCenter = [119.92, 31.17]
|
|
const taihuCenter = [119.92, 31.17]
|
|
|
const taihuZoom = 9
|
|
const taihuZoom = 9
|
|
|
-const fullExtent = new Extent({ xmin: 115, ymin: 29, xmax: 123, ymax: 33, spatialReference: SpatialReference.WGS84 })
|
|
|
|
|
|
|
+const fullExtent = new Extent({xmin: 115, ymin: 29, xmax: 123, ymax: 33, spatialReference: SpatialReference.WGS84})
|
|
|
|
|
|
|
|
// ---- create WMTS layer from URL template ----
|
|
// ---- create WMTS layer from URL template ----
|
|
|
function createWmtsLayer(cfg) {
|
|
function createWmtsLayer(cfg) {
|
|
@@ -65,9 +67,9 @@ function createWmtsLayer(cfg) {
|
|
|
const urlTemplate = cfg.urlTemplate.replace('{subDomain}', subDomains[0])
|
|
const urlTemplate = cfg.urlTemplate.replace('{subDomain}', subDomains[0])
|
|
|
// ArcGIS WebTileLayer uses {level},{col},{row} pattern
|
|
// ArcGIS WebTileLayer uses {level},{col},{row} pattern
|
|
|
const arcgisUrl = urlTemplate
|
|
const arcgisUrl = urlTemplate
|
|
|
- .replace(/\{level\}/g, '{level}')
|
|
|
|
|
- .replace(/\{row\}/g, '{row}')
|
|
|
|
|
- .replace(/\{col\}/g, '{col}')
|
|
|
|
|
|
|
+ .replace(/\{level\}/g, '{level}')
|
|
|
|
|
+ .replace(/\{row\}/g, '{row}')
|
|
|
|
|
+ .replace(/\{col\}/g, '{col}')
|
|
|
return new WebTileLayer({
|
|
return new WebTileLayer({
|
|
|
id: cfg.id,
|
|
id: cfg.id,
|
|
|
title: cfg.title,
|
|
title: cfg.title,
|
|
@@ -100,9 +102,9 @@ function createBasemapLayers(key) {
|
|
|
// ---- init ----
|
|
// ---- init ----
|
|
|
onMounted(async () => {
|
|
onMounted(async () => {
|
|
|
const layers = createBasemapLayers('taihu')
|
|
const layers = createBasemapLayers('taihu')
|
|
|
- layerGroups.value = { taihu: layers }
|
|
|
|
|
|
|
+ layerGroups.value = {taihu: layers}
|
|
|
|
|
|
|
|
- const map = new Map({ layers })
|
|
|
|
|
|
|
+ const map = new Map({layers})
|
|
|
|
|
|
|
|
const view = new MapView({
|
|
const view = new MapView({
|
|
|
container: mapNodeRef.value,
|
|
container: mapNodeRef.value,
|
|
@@ -122,7 +124,7 @@ onMounted(async () => {
|
|
|
title: cfg.name,
|
|
title: cfg.name,
|
|
|
url: cfg.url,
|
|
url: cfg.url,
|
|
|
visible: false,
|
|
visible: false,
|
|
|
- spatialReference: { wkid: 4490 },
|
|
|
|
|
|
|
+ spatialReference: {wkid: 4490},
|
|
|
outFields: ['*']
|
|
outFields: ['*']
|
|
|
})
|
|
})
|
|
|
map.add(layer)
|
|
map.add(layer)
|
|
@@ -131,7 +133,7 @@ onMounted(async () => {
|
|
|
|
|
|
|
|
// pointer move → coords
|
|
// pointer move → coords
|
|
|
view.on('pointer-move', (evt) => {
|
|
view.on('pointer-move', (evt) => {
|
|
|
- const pt = view.toMap({ x: evt.x, y: evt.y })
|
|
|
|
|
|
|
+ const pt = view.toMap({x: evt.x, y: evt.y})
|
|
|
if (pt) {
|
|
if (pt) {
|
|
|
coordLng.value = pt.longitude.toFixed(6)
|
|
coordLng.value = pt.longitude.toFixed(6)
|
|
|
coordLat.value = pt.latitude.toFixed(6)
|
|
coordLat.value = pt.latitude.toFixed(6)
|
|
@@ -164,7 +166,7 @@ onMounted(async () => {
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- emit('mapReady', { view, map })
|
|
|
|
|
|
|
+ emit('mapReady', {view, map})
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
onUnmounted(() => {
|
|
onUnmounted(() => {
|
|
@@ -209,7 +211,7 @@ defineExpose({
|
|
|
getView: () => mapView.value,
|
|
getView: () => mapView.value,
|
|
|
zoomToFull,
|
|
zoomToFull,
|
|
|
goTo(point, zoom) {
|
|
goTo(point, zoom) {
|
|
|
- mapView.value?.goTo({ target: point, zoom: zoom || 12 })
|
|
|
|
|
|
|
+ mapView.value?.goTo({target: point, zoom: zoom || 12})
|
|
|
},
|
|
},
|
|
|
addLayer(layer) {
|
|
addLayer(layer) {
|
|
|
mapView.value?.map.add(layer)
|
|
mapView.value?.map.add(layer)
|
|
@@ -222,30 +224,78 @@ defineExpose({
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped>
|
|
<style scoped>
|
|
|
-.map-container { width: 100%; height: 100%; position: relative; }
|
|
|
|
|
-.map-node { width: 100%; height: 100%; }
|
|
|
|
|
|
|
+.map-container {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.map-node {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
.basemap-panel {
|
|
.basemap-panel {
|
|
|
- position: absolute; bottom: 80px; left: 16px; z-index: 10;
|
|
|
|
|
- background: rgba(255,255,255,.92); padding: 6px 10px; border-radius: 6px;
|
|
|
|
|
- box-shadow: 0 2px 8px rgba(0,0,0,.15);
|
|
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ bottom: 80px;
|
|
|
|
|
+ left: 16px;
|
|
|
|
|
+ z-index: 10;
|
|
|
|
|
+ background: rgba(255, 255, 255, .92);
|
|
|
|
|
+ padding: 6px 10px;
|
|
|
|
|
+ border-radius: 6px;
|
|
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, .15);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.layer-btn {
|
|
.layer-btn {
|
|
|
- position: absolute; bottom: 130px; left: 16px; z-index: 10;
|
|
|
|
|
- background: white; width: 36px; height: 36px; border-radius: 6px;
|
|
|
|
|
- display: flex; align-items: center; justify-content: center; cursor: pointer;
|
|
|
|
|
- box-shadow: 0 2px 8px rgba(0,0,0,.15);
|
|
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ bottom: 130px;
|
|
|
|
|
+ left: 16px;
|
|
|
|
|
+ z-index: 10;
|
|
|
|
|
+ background: white;
|
|
|
|
|
+ width: 36px;
|
|
|
|
|
+ height: 36px;
|
|
|
|
|
+ border-radius: 6px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, .15);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.layer-btn:hover {
|
|
|
|
|
+ background: #e6f7ff;
|
|
|
}
|
|
}
|
|
|
-.layer-btn:hover { background: #e6f7ff; }
|
|
|
|
|
|
|
+
|
|
|
.full-extent-btn {
|
|
.full-extent-btn {
|
|
|
- position: absolute; top: 16px; right: 16px; z-index: 10;
|
|
|
|
|
- background: white; width: 36px; height: 36px; border-radius: 4px;
|
|
|
|
|
- display: flex; align-items: center; justify-content: center; cursor: pointer;
|
|
|
|
|
- box-shadow: 0 2px 8px rgba(0,0,0,.15);
|
|
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 16px;
|
|
|
|
|
+ right: 16px;
|
|
|
|
|
+ z-index: 10;
|
|
|
|
|
+ background: white;
|
|
|
|
|
+ width: 36px;
|
|
|
|
|
+ height: 36px;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, .15);
|
|
|
}
|
|
}
|
|
|
-.full-extent-btn:hover { background: #e6f7ff; }
|
|
|
|
|
|
|
+
|
|
|
|
|
+.full-extent-btn:hover {
|
|
|
|
|
+ background: #e6f7ff;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
.coord-bar {
|
|
.coord-bar {
|
|
|
- position: absolute; bottom: 4px; left: 50%; transform: translateX(-50%); z-index: 10;
|
|
|
|
|
- background: rgba(0,0,0,.5); color: #ccc; padding: 2px 16px; border-radius: 3px; font-size: 13px;
|
|
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ bottom: 4px;
|
|
|
|
|
+ left: 50%;
|
|
|
|
|
+ transform: translateX(-50%);
|
|
|
|
|
+ z-index: 10;
|
|
|
|
|
+ background: rgba(0, 0, 0, .5);
|
|
|
|
|
+ color: #ccc;
|
|
|
|
|
+ padding: 2px 16px;
|
|
|
|
|
+ border-radius: 3px;
|
|
|
|
|
+ font-size: 13px;
|
|
|
}
|
|
}
|
|
|
</style>
|
|
</style>
|