首页地图UI更换、地图白屏优化、图层列表拖动

dianlixunjian
徐景良 2024-12-07 09:37:36 +08:00
parent 0354e25a2e
commit aae3f7b44b
12 changed files with 250 additions and 104 deletions

BIN
public/map/bottom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

BIN
public/map/top.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

54
src/drag.ts Normal file
View File

@ -0,0 +1,54 @@
// src/directives/drag.js
import {onMounted} from "vue"
export default {
onMounted(el) {
alert(123);
let isDragging = false; // 拖动标志
let offsetX = 0, offsetY = 0; // 记录鼠标相对元素的偏移量
// 鼠标按下事件,初始化拖动
const onMouseDown = (e) => {
isDragging = true;
offsetX = e.clientX - el.getBoundingClientRect().left;
offsetY = e.clientY - el.getBoundingClientRect().top;
// 禁用文本选择,避免拖动过程中出现文本选中状态
document.body.style.userSelect = 'none';
};
// 鼠标移动事件,执行拖动
const onMouseMove = (e) => {
if (!isDragging) return;
const left = e.clientX - offsetX;
const top = e.clientY - offsetY;
el.style.position = 'absolute'; // 设置元素为绝对定位
el.style.left = `${left}px`;
el.style.top = `${top}px`;
};
// 鼠标松开事件,结束拖动
const onMouseUp = () => {
isDragging = false;
document.body.style.userSelect = ''; // 恢复文本选择
};
// 绑定事件
el.addEventListener('mousedown', onMouseDown);
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
// 清理事件监听器
el._dragDestroy = () => {
el.removeEventListener('mousedown', onMouseDown);
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
};
},
// 在组件销毁时移除事件监听器
// beforeUnmount(el) {
// if (el._dragDestroy) {
// el._dragDestroy();
// }
// },
};

View File

@ -1,5 +1,5 @@
<template>
<div class="statistical" id="bg-pan">
<div class="statistical" id="bg-pan" ref="container">
<Map
@onload="handlerOnMapLoad"
@handlerGetDetails="handlerGetDetails"
@ -84,7 +84,12 @@
<!-- 图层控制 视频监控-->
<div class="layer-center-container">
<div class="layer-center-container"
:style="style"
>
<div class="drag-area"
@mousedown="startDrag"
></div>
<LayerCenter
v-if="layerCenterShow"
@drawPolygon="drawPolygon"
@ -136,6 +141,11 @@
<script lang="ts" setup>
import { ref, onMounted, onUnmounted, computed, watch, watchEffect } from 'vue';
import useDrag from './drag';
const { style, startDrag } = useDrag();
import { useDraggable } from '@vueuse/core';
import Map from './Converge/index.vue';
import layerButton from './mapComponent/left_layerButton.vue';
@ -193,7 +203,11 @@
preTransformY.value = transformY.value;
}
startedDrag.value = true;
const layerContainer = ref(null);
const { layerContainerPositon } = useDraggable(layerContainer);
});
watch(isDragging, () => {
if (!isDragging) {
startedDrag.value = false;
@ -444,6 +458,7 @@ watchEffect(() => {
<style lang="less" scoped>
.statistical{
:deep(.ant-modal-header){
padding: 0px;
}
@ -451,6 +466,7 @@ watchEffect(() => {
overflow: hidden;
pointer-events:none;
}
}
.button-item {
width: 96px;
@ -477,9 +493,13 @@ watchEffect(() => {
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE/Edge */
user-select: none;
width:100%;
height:100vh;
position:relative;
}
#bg-pan {
}
#alertOverlay::before,
#alertOverlay::after {
@ -586,13 +606,19 @@ watchEffect(() => {
/**图层控制 视频监控**/
.layer-center-container {
width: 208px;
width:285px;
position: absolute;
bottom: 0px;
left: 20px;
z-index: 1000;
}
.drag-area{
width:245px;
height:40px;
position:absolute;
top:0px;
left:0px;
z-index:99999;
cursor:move;
}
.TC-videoi-container {
position: absolute;
bottom: 48px;

View File

@ -9,17 +9,16 @@
</div>
<div class="map-type-switch-container">
<div class="switch-button" v-if="mapAngle == '3D'" @click="handlerChangeMapAngle()">
<TableOutlined style="font-size: 20px; position: relative; top: 1px; left: -6px" />
<!-- <TableOutlined style="font-size: 20px; position: relative; top: 1px; left: -6px" /> -->
<span>&nbsp;二维地图</span>
</div>
<div class="switch-button" v-else @click="handlerChangeMapAngle()">
<GlobalOutlined style="font-size: 20px; position: relative; top: 1px; left: -6px" />
<!-- <GlobalOutlined style="font-size: 20px; position: relative; top: 1px; left: -6px" /> -->
<span>&nbsp;三维地图</span>
</div>
<div class="home-button" @click="handlerInitialize">
<HomeOutlined />
</div>
</div>
</div>
@ -102,21 +101,7 @@
`https://t0.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=${TINADITU_TOKEN}`,
],
tileSize: 256,
},
yaogan: {
type: 'raster',
tiles: [VITE_GLOB_YAOGANYINGXIANG_SERVER],
tileSize: 256,
minzoom: 16,
maxzoom: 24,
},
yingxiang: {
type: 'raster',
tiles: [VITE_GLOB_YINGXIANG_SERVER],
tileSize: 256,
minzoom: 16,
maxzoom: 24,
},
}
},
layers: [
{
@ -130,27 +115,7 @@
type: 'raster',
source: 'raster-tiles',
maxZoom: 32,
},
{
id: 'yaogan',
type: 'raster',
source: 'yaogan',
layout: {
visibility: networkType.value == 'LAN' ? 'visible' : 'none',
},
minzoom: 9,
maxzoom: 15,
},
{
id: 'yingxiang',
type: 'raster',
source: 'yingxiang',
layout: {
visibility: networkType.value == 'LAN' ? 'visible' : 'none',
},
minzoom: 13,
maxzoom: 24,
},
}
// {
// id: 'tdt-wms-tiles',
// type: 'raster',
@ -168,50 +133,98 @@
// load map info
async function loadMapInfo(){
try{
await axios.get(VITE_GLOB_LAN_API_URL+"/api/DroneCloudQuery/IsPublic").then(res=>{
if(res.data.result){
networkType.value = "WAN";
}else{
networkType.value = "LAN";
}
})
}catch(e){
networkType.value = "WAN";
}finally{
map = initMap();
map.on('load', () => {
//mapbox-gl-utils
U.init(map);
mp = new MP(map);
function loadMapInfo(){
//
map.addSource('mapbox-dem', {
type: 'raster-dem',
tiles: [VITE_GLOB_API_URL_VAR.value + '/mapbox_terrain/{z}/{x}/{y}.png'],
tileSize: 256,
maxzoom: 13,
minzoom: 10,
});
map.setTerrain({ source: 'mapbox-dem', exaggeration: 1 });
map = initMap();
// 2D
map.easeTo({ pitch: 0, bearing: 0, duration: 1000 });
map.dragRotate.disable(); //
map.pitchWithRotate = false; //
mapAngle.value = '2D';
map.on('load', () => {
//mapbox-gl-utils
U.init(map);
mp = new MP(map);
handlerCheckUserOrgs();
// handlerLoadMaskLayer();
getMaskData();
handlerDealStreet();
handlerDealCountry();
//
map.addSource('mapbox-dem', {
type: 'raster-dem',
tiles: [VITE_GLOB_API_URL_VAR.value + '/mapbox_terrain/{z}/{x}/{y}.png'],
tileSize: 256,
maxzoom: 13,
minzoom: 10,
});
map.setTerrain({ source: 'mapbox-dem', exaggeration: 1 });
//
addMonitorLayer();
});
}
// 2D
map.easeTo({ pitch: 0, bearing: 0, duration: 1000 });
map.dragRotate.disable(); //
map.pitchWithRotate = false; //
mapAngle.value = '2D';
handlerCheckUserOrgs();
// handlerLoadMaskLayer();
getMaskData();
handlerDealStreet();
handlerDealCountry();
//
addMonitorLayer();
//
try{
axios.get(VITE_GLOB_LAN_API_URL+"/api/DroneCloudQuery/IsPublic").then(res=>{
if(res.data.result){
networkType.value = "WAN";
}else{
networkType.value = "LAN";
//
loadYingXiangLayer()
}
})
}catch(e){
networkType.value = "WAN";
}finally{
}
});
}
function loadYingXiangLayer(){
map.addSource("yaogan", {
type: 'raster',
tiles: [VITE_GLOB_YAOGANYINGXIANG_SERVER],
tileSize: 256,
minzoom: 16,
maxzoom: 24,
})
map.addSource("yingxiang", {
type: 'raster',
tiles: [VITE_GLOB_YINGXIANG_SERVER],
tileSize: 256,
minzoom: 16,
maxzoom: 24,
})
map.addLayer({
id: 'yaogan',
type: 'raster',
source: 'yaogan',
layout: {
visibility: networkType.value == 'LAN' ? 'visible' : 'none',
},
minzoom: 9,
maxzoom: 15,
})
map.addLayer({
id: 'yingxiang',
type: 'raster',
source: 'yingxiang',
layout: {
visibility: networkType.value == 'LAN' ? 'visible' : 'none',
},
minzoom: 13,
maxzoom: 24,
})
}
//
const polygonVisibility = ref<String>('none');
@ -703,6 +716,7 @@
//
const handlerDealStreet = (countyName: String = '临沂市'): void => {
axios({
method: 'get',
url: `http://175.27.168.120:8080/geoserver/linyishi/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=linyishi%3Azhenjie&maxFeatures=10000&outputFormat=application%2Fjson`,
@ -719,8 +733,6 @@
map.addSource('streetSource', {
type: 'geojson',
data: geojson,
minzoom: 10,
maxzoom: 24,
});
map.addLayer({
id: 'streetLayer',
@ -749,6 +761,8 @@
'text-halo-color': '#fff',
'text-halo-width': 2,
},
minzoom: 10,
maxzoom: 24,
});
}
};
@ -867,6 +881,7 @@
mapboxgl.accessToken = MAPBOX_TOKEN;
//
loadMapInfo();
})
@ -1149,7 +1164,7 @@
}
.map-type-switch-container {
width: 280px;
width: 208px;
height: 40px;
position: absolute;
top: 72px;
@ -1175,14 +1190,12 @@
}
.home-button {
width: 100px;
height: 100px;
width:40px;
height:40px;
background: url(/map/home-btn.png);
background-size: 100% 100%;
float: right;
position: relative;
top: -25px;
line-height: 100px;
text-align: center;
}
::v-deep .mapboxgl-ctrl-logo {

View File

@ -0,0 +1,51 @@
import { ref, onBeforeUnmount } from 'vue';
export default function useDrag() {
const isDragging = ref(false); // 是否正在拖动
const offsetX = ref(0); // 鼠标按下时的 X 坐标偏移
const offsetY = ref(0); // 鼠标按下时的 Y 坐标偏移
const style = ref({
position: 'absolute', // 设置为绝对定位
top: '200px', // 初始位置
left: '70px', // 初始位置
});
// 鼠标按下时,记录偏移量并开始拖动
const startDrag = (event: MouseEvent) => {
isDragging.value = true;
offsetX.value = event.clientX - (event.target as HTMLElement).getBoundingClientRect().left;
offsetY.value = event.clientY - (event.target as HTMLElement).getBoundingClientRect().top;
// 添加鼠标移动和鼠标松开事件监听
document.addEventListener('mousemove', onDrag);
document.addEventListener('mouseup', stopDrag);
};
// 鼠标移动时,更新元素的位置
const onDrag = (event: MouseEvent) => {
if (isDragging.value) {
style.value.left = `${event.clientX - offsetX.value - 200}px`;
style.value.top = `${event.clientY - offsetY.value - 100}px`;
}
};
// 鼠标松开时,停止拖动
const stopDrag = () => {
isDragging.value = false;
document.removeEventListener('mousemove', onDrag);
document.removeEventListener('mouseup', stopDrag);
};
// 在组件卸载时移除事件监听
onBeforeUnmount(() => {
document.removeEventListener('mousemove', onDrag);
document.removeEventListener('mouseup', stopDrag);
});
return {
style,
startDrag,
};
}

View File

@ -3,8 +3,10 @@
<div class="title">
图层资源
<div class="hidden-button" @click="openLayer = !openLayer">
<Icon v-if="openLayer" :icon="'ic:outline-unfold-less'" :size="18"/>
<Icon v-else :icon="'ic:outline-unfold-more'" :size="18"/>
<!-- <Icon v-if="openLayer" :icon="'ic:outline-unfold-less'" :size="18"/> -->
<img v-if="openLayer" src="/public/map/top.png" alt="">
<img v-else src="/public/map/bottom.png" alt="">
<!-- <Icon v-else :icon="'ic:outline-unfold-more'" :size="18"/> -->
</div>
</div>
<div class="layers-container">
@ -242,22 +244,22 @@
transition: 0.5s;
&::before {
content: '';
height: 70%;
width: 20px;
height: 26px;
width: 26px;
position: absolute;
bottom: 5px;
left: 5px;
background: url('/videosupervision/main-left.png');
bottom: 0px;
left: 0px;
background: url('/map/layer-center-left.png');
background-size: 100% 100%;
}
&::after {
content: '';
height: 70%;
width: 20px;
height: 26px;
width: 26px;
position: absolute;
bottom: 5px;
right: 5px;
background: url('/videosupervision/main-right.png');
bottom: 0px;
right: 0px;
background: url('/map/layer-center-right.png');
background-size: 100% 100%;
}