带接口api

This commit is contained in:
任娜 2025-06-30 10:40:22 +08:00
parent b48a792744
commit 6402fbb3ef
6 changed files with 192 additions and 36 deletions

BIN
src/assets/images/layer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -8,6 +8,8 @@
<OpenLayersZoomControl
:map="map"
:resetView="resetView"
:routeLayerVisible="routeLayerVisible"
@layerToggle="toggleRouteLayer"
@compass="compass"
@zoomIn="zoomIn"
@zoomOut="zoomOut"
@ -29,7 +31,7 @@
</template>
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import { ref, onMounted, onUnmounted, watch } from "vue";
import Map from "ol/Map";
import View from "ol/View";
import TileLayer from "ol/layer/Tile";
@ -45,6 +47,18 @@ import OpenLayersMapInfo from "./controls/OpenLayersMapInfo.vue";
import OverviewMap from 'ol/control/OverviewMap';
import ScaleLine from 'ol/control/ScaleLine';
import OpenLayersScaleControl from "./controls/OpenLayersScaleControl.vue";
import OSM from 'ol/source/OSM';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import Feature from 'ol/Feature';
import Point from 'ol/geom/Point';
import LineString from 'ol/geom/LineString';
import Polygon from 'ol/geom/Polygon';
import Style from 'ol/style/Style';
import Icon from 'ol/style/Icon';
import Stroke from 'ol/style/Stroke';
import Fill from 'ol/style/Fill';
import { fromLonLat } from 'ol/proj';
// EPSG:4528
proj4.defs(
@ -78,6 +92,12 @@ const minZoom = 7; // 最小缩放级别
const maxZoom = 15; //
const initialZoom = 8; // 7.578
const routeLayerVisible = ref(false); // 线
function toggleRouteLayer() {
routeLayerVisible.value = !routeLayerVisible.value;
}
onMounted(() => {
//
let savedView = null;
@ -110,6 +130,19 @@ onMounted(() => {
rotation: savedView ? savedView.rotation : rotation, // 使
});
// 使OSM
const baseLayer = new TileLayer({
source: new OSM()
});
//
const vectorSource = new VectorSource();
const vectorLayer = new VectorLayer({
source: vectorSource,
zIndex: 2,
visible: routeLayerVisible.value
});
// .ol3
map.value = new Map({
target: mapContainer.value,
@ -124,18 +157,7 @@ onMounted(() => {
constrainResolution: true,
}),
]),
layers: [
// 使TileLayerTileSuperMapRest
new TileLayer({
source: new TileSuperMapRest({
url: "http://10.96.3.10:8090/iserver/services/map-QDJC_DT-GX3/rest/maps/QDJC2DZT",
projection: "EPSG:4528",
tileGrid: tileGrid,
wrapX: false,
attributions: "", //
}),
}),
],
layers: [baseLayer, vectorLayer],
view: view,
});
@ -184,7 +206,73 @@ onMounted(() => {
}
}, 500);
//
const pointFeature = new Feature({
geometry: new Point([13394416, 4136655])
});
pointFeature.setStyle(new Style({
image: new Icon({
src: 'https://openlayers.org/en/latest/examples/data/icon.png',
scale: 0.7
})
}));
vectorSource.addFeature(pointFeature);
// 线
const lineFeature = new Feature({
geometry: new LineString([
[13394416, 4136655],
[13395000, 4137000]
])
});
lineFeature.setStyle(new Style({
stroke: new Stroke({
color: 'blue',
width: 2
})
}));
vectorSource.addFeature(lineFeature);
//
const polygonFeature = new Feature({
geometry: new Polygon([[
[13394416, 4136655],
[13395000, 4136655],
[13395000, 4137000],
[13394416, 4137000],
[13394416, 4136655]
]])
});
polygonFeature.setStyle(new Style({
stroke: new Stroke({ color: 'red', width: 2 }),
fill: new Fill({ color: 'rgba(255,0,0,0.2)' })
}));
vectorSource.addFeature(polygonFeature);
// --- 线 ---
function randomLngLat() {
const lng = 120.1 + Math.random() * 0.4;
const lat = 35.9 + Math.random() * 0.4;
return [lng, lat];
}
// 3线5~8
for (let i = 0; i < 3; i++) {
const points = [];
const count = 5 + Math.floor(Math.random() * 4);
for (let j = 0; j < count; j++) {
points.push(fromLonLat(randomLngLat()));
}
const lineFeature = new Feature({
geometry: new LineString(points)
});
lineFeature.setStyle(new Style({
stroke: new Stroke({
color: ['red', 'blue', 'green'][i % 3],
width: 3
})
}));
vectorSource.addFeature(lineFeature);
}
//
setTimeout(() => {
@ -211,6 +299,10 @@ onMounted(() => {
// OpenLayers
// UI
});
watch(routeLayerVisible, (val) => {
vectorLayer.setVisible(val);
});
});
onUnmounted(() => {

View File

@ -39,10 +39,10 @@ function handleMouseMove(event) {
// 3. WGS84
try {
const [lng, lat] = transform(coordinate, 'EPSG:4528', 'EPSG:4326');
console.log('WGS84坐标:', lng, lat);
//console.log('WGS84:', lng, lat);
wgs84Text.value = `WGS84: 经度=${lng.toFixed(6)}°, 纬度=${lat.toFixed(6)}°`;
} catch (error) {
console.error('坐标转换失败:', error);
// console.error(':', error);
wgs84Text.value = 'WGS84: 转换错误';
}
} else {

View File

@ -1,7 +1,25 @@
<template>
<div class="zoom-control">
<LayerSwitcher class="layer-switcher" :map="map" @layerChange="onLayerChange" ref="layerSwitcherRef" />
<el-popover
placement="right"
width="160"
trigger="click"
v-model:visible="popoverVisible"
popper-class="layer-popover"
>
<el-checkbox
:model-value="props.routeLayerVisible"
@change="onLayerToggle"
>道路图层</el-checkbox>
<template #reference>
<div
class="layer-toggle"
:class="{ active: props.routeLayerVisible }"
@click="handleLayerBtnClick"
title="图层控制"
></div>
</template>
</el-popover>
<div class="compass" @click="onCompass"></div>
<div class="zoom-in" @click="onZoomIn"></div>
<div class="zoom-out" @click="onZoomOut"></div>
@ -10,6 +28,7 @@
<script setup>
import { ref, onMounted } from 'vue';
import { ElPopover, ElCheckbox } from 'element-plus';
// import LayerSwitcher from './LayerSwitcher.vue';
// props
@ -18,6 +37,10 @@ const props = defineProps({
resetView: {
type: Function,
default: null
},
routeLayerVisible: {
type: Boolean,
default: false
}
});
@ -25,7 +48,9 @@ const props = defineProps({
const layerSwitcherRef = ref(null);
//
const emit = defineEmits(['compass', 'zoomIn', 'zoomOut', 'layerChange']);
const emit = defineEmits(['compass', 'zoomIn', 'zoomOut', 'layerChange', 'layerToggle']);
const popoverVisible = ref(false);
// /
function onCompass() {
@ -57,6 +82,14 @@ function onLayerChange(layerInfo) {
emit('layerChange', layerInfo);
}
function onLayerToggle() {
emit('layerToggle');
}
function handleLayerBtnClick() {
popoverVisible.value = !popoverVisible.value;
}
//
defineExpose({
//
@ -83,6 +116,22 @@ defineExpose({
gap: 25px;
}
.layer-toggle {
width: 40px;
height: 40px;
background: url("../../../assets/images/layer.png") no-repeat;
background-size: 100% 100%;
cursor: pointer;
z-index: 3000;
border-radius: 8px;
border: 2px solid transparent;
box-sizing: border-box;
transition: border 0.2s;
}
.layer-toggle.active {
border: 2px solid #409eff;
box-shadow: 0 0 8px #409eff44;
}
.compass {
width: 40px;
height: 40px;
@ -91,15 +140,6 @@ defineExpose({
cursor: pointer;
z-index: 3000;
}
.layer-switcher{
z-index: 3000;
width: 40px;
height: 40px;
background: url("../../../assets/images/layer.png") no-repeat;
background-size: 100% 100%;
cursor: pointer;
}
.zoom-in {
background: url("../../../assets/images/zoomOut.png") no-repeat;
background-size: 100% 100%;
@ -108,7 +148,6 @@ defineExpose({
height: 40px;
cursor: pointer;
}
.zoom-out {
background: url("../../../assets/images/zoomIn.png") no-repeat;
background-size: 100% 100%;
@ -120,7 +159,7 @@ defineExpose({
/* 响应式调整 */
@media (max-width: 768px) {
.zoom-in, .zoom-out, .compass {
.zoom-in, .zoom-out, .compass, .layer-toggle {
width: 28px;
height: 28px;
background-size: 80%;
@ -128,4 +167,9 @@ defineExpose({
background-repeat: no-repeat;
}
}
.layer-popover {
padding: 12px 16px;
min-width: 120px;
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<div class="platform-overview">
<div class="platform-overview platform-no-padding">
<OpenLayersMap />
<CarAlarm />
<!-- 右侧展开/收起按钮 -->
@ -15,7 +15,7 @@
</template>
<script setup>
import { ref } from 'vue';
import { ref, onMounted, onUnmounted } from 'vue';
import OpenLayersMap from '../../components/map/OpenLayersMap.vue';
import CarAlarm from '../../components/map/info/carClarm.vue';
import Eventlist from '../../components/map/info/eventlist.vue';
@ -27,17 +27,24 @@ const showEventList = ref(false);
function toggleEventList() {
showEventList.value = !showEventList.value;
}
onMounted(() => {
document.querySelector('.app-main')?.classList.add('platform-no-padding');
});
onUnmounted(() => {
document.querySelector('.app-main')?.classList.remove('platform-no-padding');
});
</script>
<style scoped>
<style scoped lang="scss">
.platform-overview {
width: 100%;
height: 100%;
height:calc(100vh - 60px);
position: relative;
display: flex;
flex-direction: column;
overflow: hidden;
min-height: 0;
z-index:1;
}
/* 右侧展开/收起按钮样式 */
@ -51,4 +58,17 @@ function toggleEventList() {
transform: translateY(-50%);
cursor: pointer;
}
</style>
/* 只影响本页精准去除AppMain的左右padding */
:deep(.platform-no-padding) .app-main {
padding-left: 0 !important;
padding-right: 0 !important;
}
</style>
<style>
.app-main.platform-no-padding {
padding-left: 0 !important;
padding-right: 0 !important;
}
</style>

View File

@ -31,7 +31,7 @@ export default defineConfig(({ mode, command }) => {
proxy: {
// https://cn.vitejs.dev/config/#server-proxy
'/dev-api': {
target: 'http://10.0.0.17:8099',
target: 'http://localhost:8099',
changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-api/, '')
}