| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- <template>
- <view class="map-page">
- <!-- 地图组件 -->
- <map-view
- ref="mapViewRef"
- :latitude="latitude"
- :longitude="longitude"
- :zoom="zoom"
- :markers="markers"
- :show-location="true"
- @markerTap="handleMarkerTap"
- @locationUpdate="handleLocationUpdate"
- @layerChange="handleLayerChange"
- @layerChangeError="handleLayerChangeError"
- />
- <!-- 操作面板 -->
- <view class="operation-panel">
- <view class="panel-btn" @click="handleAddMarker">
- <text class="panel-btn-text">添加标记</text>
- </view>
- <view class="panel-btn" @click="handleAddRoute">
- <text class="panel-btn-text">绘制路线</text>
- </view>
- <view class="panel-btn" @click="handleAddCircle">
- <text class="panel-btn-text">绘制圆形</text>
- </view>
- <view class="panel-btn" @click="handleClear">
- <text class="panel-btn-text">清除覆盖物</text>
- </view>
- </view>
- </view>
- </template>
- <script setup lang="uts">
- import { ref, type ComponentPublicInstance } from 'vue'
- import type { MapMarker, MapLayerType } from '../../../types/map'
- // 地图引用(使用 ComponentPublicInstance 类型)
- const mapViewRef = ref<ComponentPublicInstance | null>(null)
- // 地图中心点
- const latitude = ref<number>(32.556211)
- const longitude = ref<number>(111.494811)
- // 地图缩放级别(3-18,数字越大越详细)
- const zoom = ref<number>(13)
- // 标记点列表(初始为空)
- const markers = ref<MapMarker[]>([])
- // 路线数据类型
- type RouteData = {
- points: any[]
- color: string
- width: number
- name: string
- }
- // 路线列表
- const routes = ref<RouteData[]>([])
- // 圆形数据类型
- type CircleData = {
- latitude: number
- longitude: number
- radius: number
- strokeColor: string
- fillColor: string
- name: string
- }
- // 圆形列表
- const circles = ref<CircleData[]>([])
- /**
- * 圆形半径(单位:米,可修改)
- * 示例:
- * - 1000 = 1公里
- * - 5000 = 5公里
- * - 10000 = 10公里
- * - 20000 = 20公里
- */
- const circleRadius = ref<number>(1000)
- // 标记点点击
- const handleMarkerTap = (e: any): void => {
- console.log('标记点击事件:', e)
- uni.showToast({
- title: '标记被点击',
- icon: 'none'
- })
- }
- // 位置更新
- const handleLocationUpdate = (location: any): void => {
- // 提取属性(any 类型不能直接访问属性)
- const locationObj = location as UTSJSONObject
- const lat = locationObj['latitude'] as number
- const lon = locationObj['longitude'] as number
-
- latitude.value = lat
- longitude.value = lon
- }
- // 模拟接口请求,获取标记点数据
- const fetchMarkers = async (): Promise<MapMarker[]> => {
- // 模拟网络延迟
- await new Promise<void>((resolve) => {
- setTimeout(() => {
- resolve()
- }, 800)
- })
-
- // 在地图中心点周围生成50个随机标记点
- const mockMarkers: MapMarker[] = []
- const baseId = markers.value.length
-
- // 项目类型列表
- const projectTypes = ['水库', '河流', '水闸', '泵站', '灌区', '堤防', '水文站']
-
- for (let i = 0; i < 50; i++) {
- // 在中心点周围0.1度范围内随机生成(约11公里范围)
- const randomLat = latitude.value + (Math.random() - 0.5) * 0.1
- const randomLng = longitude.value + (Math.random() - 0.5) * 0.1
- const projectType = projectTypes[Math.floor(Math.random() * projectTypes.length)]
-
- mockMarkers.push({
- id: baseId + i + 1,
- latitude: randomLat,
- longitude: randomLng,
- title: `${projectType}${i + 1}`,
- iconPath: '/static/images/map/project.png',
- width: 32,
- height: 32
- })
- }
-
- return mockMarkers
- }
- // 模拟接口请求,获取路线数据
- const fetchRoutes = async (): Promise<RouteData[]> => {
- // 模拟网络延迟
- await new Promise<void>((resolve) => {
- setTimeout(() => {
- resolve()
- }, 600)
- })
-
- // 生成3条路线的模拟数据
- const mockRoutes: RouteData[] = []
-
- // 路线1:东西向路线(红色)
- const route1Points: any[] = []
- const startLat1 = latitude.value + 0.02
- for (let i = 0; i < 10; i++) {
- const lng = longitude.value - 0.03 + i * 0.006
- const lat = startLat1 + Math.sin(i * 0.5) * 0.005
- route1Points.push({
- latitude: lat,
- longitude: lng
- })
- }
- mockRoutes.push({
- points: route1Points,
- color: '#FF5733',
- width: 4,
- name: '主干道路线'
- })
-
- // 路线2:南北向路线(蓝色)
- const route2Points: any[] = []
- const startLng2 = longitude.value - 0.02
- for (let i = 0; i < 8; i++) {
- const lat = latitude.value - 0.02 + i * 0.005
- const lng = startLng2 + Math.cos(i * 0.6) * 0.008
- route2Points.push({
- latitude: lat,
- longitude: lng
- })
- }
- mockRoutes.push({
- points: route2Points,
- color: '#3498DB',
- width: 5,
- name: '河流路线'
- })
-
- // 路线3:环形路线(绿色)
- const route3Points: any[] = []
- const centerLat = latitude.value - 0.01
- const centerLng = longitude.value + 0.01
- const radius = 0.015
- for (let i = 0; i <= 12; i++) {
- const angle = i * Math.PI / 6
- const lat = centerLat + radius * Math.sin(angle)
- const lng = centerLng + radius * Math.cos(angle)
- route3Points.push({
- latitude: lat,
- longitude: lng
- })
- }
- mockRoutes.push({
- points: route3Points,
- color: '#27AE60',
- width: 3,
- name: '环形巡查路线'
- })
-
- return mockRoutes
- }
- // 添加标记
- const handleAddMarker = async (): Promise<void> => {
- try {
- uni.showLoading({
- title: '加载中...'
- })
-
- // 模拟接口请求
- const newMarkers = await fetchMarkers()
-
- // 添加到列表
- for (let i = 0; i < newMarkers.length; i++) {
- markers.value.push(newMarkers[i])
- }
-
- // 批量添加到地图
- if (mapViewRef.value != null) {
- mapViewRef.value.$callMethod('addMarkers', newMarkers)
- }
-
- uni.hideLoading()
- uni.showToast({
- title: `成功添加${newMarkers.length}个标记点`,
- icon: 'success'
- })
- } catch (e: any) {
- uni.hideLoading()
- uni.showToast({
- title: '加载失败',
- icon: 'none'
- })
- }
- }
- // 绘制路线
- const handleAddRoute = async (): Promise<void> => {
- try {
- uni.showLoading({
- title: '加载中...'
- })
-
- // 模拟接口请求
- const newRoutes = await fetchRoutes()
-
- // 添加到列表
- for (let i = 0; i < newRoutes.length; i++) {
- routes.value.push(newRoutes[i])
- }
-
- // 批量绘制路线
- if (mapViewRef.value != null) {
- for (let i = 0; i < newRoutes.length; i++) {
- const route = newRoutes[i]
- mapViewRef.value.$callMethod('addPolyline', route.points, route.color, route.width)
- }
- }
-
- uni.hideLoading()
- uni.showToast({
- title: `成功绘制${newRoutes.length}条路线`,
- icon: 'success'
- })
- } catch (e: any) {
- uni.hideLoading()
- uni.showToast({
- title: '加载失败',
- icon: 'none'
- })
- }
- }
- // 绘制圆形
- const handleAddCircle = (): void => {
- if (mapViewRef.value != null) {
- // 以地图中心点为圆心绘制圆形
- const circle: CircleData = {
- latitude: latitude.value,
- longitude: longitude.value,
- radius: circleRadius.value,
- strokeColor: 'rgb(12, 113, 247)',
- fillColor: 'rgb(12, 113, 247)',
- name: `圆形-${circles.value.length + 1}`
- }
-
- // 添加到列表
- circles.value.push(circle)
-
- // 绘制到地图
- mapViewRef.value.$callMethod(
- 'addCircle',
- circle.latitude,
- circle.longitude,
- circle.radius,
- circle.strokeColor,
- circle.fillColor
- )
-
- const radiusKm = circleRadius.value / 1000
- }
- }
- // 清除覆盖物
- const handleClear = (): void => {
- if (mapViewRef.value != null) {
- // 清除覆盖物(路线、圆形、多边形)
- mapViewRef.value.$callMethod('clearOverlays')
- // 清除标记点
- mapViewRef.value.$callMethod('clearMarkers')
-
- // 清空本地列表
- markers.value = []
- routes.value = []
- circles.value = []
- uni.showToast({
- title: '清除成功',
- icon: 'success'
- })
- }
- }
- // 图层切换成功事件
- const handleLayerChange = (layerType: MapLayerType): void => {
- console.log('图层切换成功:', layerType)
-
- // 可以在这里执行图层切换后的额外逻辑
- // 例如:刷新地图标记、重新加载数据等
- }
- // 图层切换失败事件
- const handleLayerChangeError = (error: string): void => {
- console.error('图层切换失败:', error)
-
- // 可以在这里执行错误处理逻辑
- // 例如:记录错误日志、上报监控等
- }
- </script>
- <style lang="scss">
- .map-page {
- position: relative;
- width: 100%;
- height: 100%;
- }
- .operation-panel {
- position: absolute;
- left: 20rpx;
- bottom: 30rpx;
- flex-direction: column;
- }
- .panel-btn {
- margin-bottom: 15rpx;
- padding: 0 30rpx;
- height: 70rpx;
- background-color: #ffffff;
- border-radius: 8rpx;
- box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.15);
- justify-content: center;
- align-items: center;
- &-text {
- font-size: 26rpx;
- color: #333333;
- }
- }
- </style>
|