ly-front/src/views/mapControl/index.vue

255 lines
6.6 KiB
Vue
Raw Normal View History

2025-03-31 15:26:29 +00:00
<template>
2025-06-16 14:22:14 +00:00
<div class="HomeMap">
2025-06-19 15:41:07 +00:00
<div class="zoom-level" @click="soundAndMenu">
<img :src="zoomLevelImage" alt="" />
</div>
2025-06-16 14:22:14 +00:00
<div id="map" ref="olMap" class="map-container"></div>
2025-04-13 08:23:44 +00:00
<div class="pointingNorth" @click="mapNorth">
2025-06-19 15:41:07 +00:00
<img src="@/assets/img/user.png" alt="" />
<img src="@/assets/img/setup.png" alt="" />
<img src="@/assets/img/query.png" alt="" />
</div>
<div class="configuration">
<div class="refresh" @click="refreshClick">
2025-06-19 15:41:07 +00:00
<img src="@/assets/img/refresh.png" alt="" />
</div>
<div class="refresh" @click="positionClick">
2025-06-19 15:41:07 +00:00
<img src="@/assets/img/icon_postions.png" alt="" />
</div>
<div class="refresh" @click="modelClick">
2025-06-19 15:41:07 +00:00
<img src="@/assets/img/icon_model.png" alt="" />
</div>
2025-04-13 08:23:44 +00:00
</div>
2025-03-31 15:26:29 +00:00
</div>
</template>
<script>
import { mapGetters } from "vuex";
2025-06-16 14:22:14 +00:00
import Map from "ol/Map";
import View from "ol/View";
import TileLayer from "ol/layer/Tile";
import { fromLonLat } from "ol/proj";
import XYZ from "ol/source/XYZ";
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 Style from "ol/style/Style";
import Icon from "ol/style/Icon";
import Stroke from "ol/style/Stroke";
import Fill from "ol/style/Fill";
import Text from "ol/style/Text";
import CircleStyle from "ol/style/Circle";
import Static from "ol/source/ImageStatic.js";
import uaImg from "@/assets/img/icon_uav.png";
2025-03-31 15:26:29 +00:00
export default {
name: "HomeMap",
data() {
return {
2025-06-16 14:22:14 +00:00
map: null,
2025-06-19 15:41:07 +00:00
zoomLevel: null,
isZoomedIn: true,
isZoomedOut: false,
showPermissionPrompt: false
2025-03-31 15:26:29 +00:00
};
},
created() {
2025-06-16 14:22:14 +00:00
// 清空控制台(可选)
2025-03-31 15:26:29 +00:00
// console.clear();
},
mounted() {
2025-06-16 14:22:14 +00:00
this.initMap();
2025-03-31 15:26:29 +00:00
},
computed: {
2025-06-19 15:41:07 +00:00
...mapGetters(["statePage", "cityCode"]),
zoomLevelImage() {
return this.isZoomedIn
? require("@/assets/img/sound.png")
: require("@/assets/img/mute.png");
}
2025-03-31 15:26:29 +00:00
},
methods: {
refreshClick() {
// 刷新页面
window.location.reload();
},
positionClick() {
console.log("位置点击");
this.$store.commit("SET_POSITIONPOINT", true);
},
modelClick() {
// 切换底图
const newBaseMap = this.currentBaseMap === "gaode" ? "tianditu" : "gaode";
this.map.getLayers().forEach((layer) => {
const name = layer.get("name");
if (name === "gaode" || name === "tianditu") {
layer.setVisible(name === newBaseMap);
}
});
this.currentBaseMap = newBaseMap;
},
2025-06-19 15:41:07 +00:00
soundAndMenu() {
this.isZoomedIn = !this.isZoomedIn;
this.$store.commit("SET_ISZOOMEDIN", this.isZoomedIn);
// const media = document.getElementById("uavAudio");
// if (media) {
// media.muted = !this.isZoomedIn; // isZoomedIn为true时静音
// if (!this.isZoomedIn) {
// // 取消静音时尝试播放
// media.play().catch((error) => {
// console.log("播放失败,可能需要用户交互:", error);
// });
// }
// }
2025-06-19 15:41:07 +00:00
},
2025-06-16 14:22:14 +00:00
initMap() {
// 初始化 OpenLayers 地图
this.map = new Map({
target: this.$refs.olMap,
layers: [
new TileLayer({
name: "gaode", // 图层名称
2025-06-16 14:22:14 +00:00
visible: true,
source: new XYZ({
visible: true,
url: "http://webrd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=2&scale=1&style=8"
})
}),
new TileLayer({
name: "tianditu",
source: new XYZ({
url: "https://{a-d}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png"
}),
visible: false
2025-06-16 14:22:14 +00:00
})
],
view: new View({
projection: "EPSG:3857",
center: fromLonLat([117.337103, 39.040924]), // 经纬度转投影坐标
2025-06-16 14:22:14 +00:00
zoom: 10,
minZoom: 3,
maxZoom: 18,
constrainRotation: false // 允许旋转
})
2025-03-31 15:26:29 +00:00
});
2025-06-16 14:22:14 +00:00
// 保存地图实例到全局(与 Mars3D 的 window.marsMap 类似)
window.olMap = this.map;
// 处理地图加载完成后的逻辑
this.onMapLoad(this.map);
// 绑定点击事件
this.map.on("click", this.mapClickHandler);
// 绑定缩放/移动结束事件
this.map.getView().on("change:resolution", this.mapZoomHandler);
this.map.getView().on("change:center", this.mapZoomHandler);
2025-03-31 15:26:29 +00:00
},
2025-06-16 14:22:14 +00:00
mapClickHandler(event) {
// 处理地图点击事件
console.log("地图点击:", event);
2025-04-01 16:12:21 +00:00
},
2025-06-16 14:22:14 +00:00
mapZoomHandler() {
// 获取当前缩放等级
this.zoomLevel = Math.round(this.map.getView().getZoom());
2025-04-01 16:12:21 +00:00
},
2025-03-31 15:26:29 +00:00
onMapLoad(map) {
2025-06-16 14:22:14 +00:00
// 地图加载完成后的处理
const camera = window.mapConfig || {};
2025-04-12 15:15:32 +00:00
if (camera.isCamera) {
2025-06-16 14:22:14 +00:00
// 设置视角约束
map
.getView()
.setCenter(
fromLonLat([camera.cameraLon || 0, camera.cameraLat || 0])
);
map.getView().setMinZoom(3); // 最小缩放等级
map.getView().setMaxZoom(18); // 最大缩放等级
2025-04-12 15:15:32 +00:00
}
2025-04-13 08:23:44 +00:00
},
mapNorth() {
2025-06-16 14:22:14 +00:00
// 指北:将地图旋转角度重置为 0
const view = this.map.getView();
const currentCenter = view.getCenter();
const currentZoom = view.getZoom();
view.animate({
center: currentCenter,
zoom: currentZoom < 3 ? 10 : currentZoom, // 确保最小缩放等级
rotation: 0, // 指北
duration: 500 // 动画持续时间
2025-04-13 11:05:15 +00:00
});
2025-03-31 15:26:29 +00:00
}
}
};
</script>
2025-06-16 14:22:14 +00:00
2025-03-31 15:26:29 +00:00
<style scoped lang="scss">
2025-06-16 14:22:14 +00:00
.HomeMap {
2025-03-31 15:26:29 +00:00
width: 100%;
height: 100%;
2025-06-16 14:22:14 +00:00
position: relative;
2025-04-01 16:12:21 +00:00
.zoom-level {
position: absolute;
2025-06-19 15:41:07 +00:00
top: 60px;
right: 40px;
2025-06-16 14:22:14 +00:00
z-index: 1000;
2025-04-01 16:12:21 +00:00
color: #fff;
2025-06-19 15:41:07 +00:00
img {
width: 48px;
height: 48px;
}
}
.configuration {
position: absolute;
bottom: 32px;
right: 40px;
z-index: 1000;
color: #fff;
width: 29px;
height: 174px;
background-color: rgba(209, 242, 255, 0.9);
padding: 19px 8px;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
.refresh {
width: 32px;
height: 32px;
img {
width: 32px;
height: 32px;
}
}
2025-04-01 16:12:21 +00:00
}
2025-03-31 15:26:29 +00:00
2025-06-16 14:22:14 +00:00
.map-container {
2025-03-31 15:26:29 +00:00
width: 100%;
height: 100%;
}
2025-06-16 14:22:14 +00:00
2025-04-13 08:23:44 +00:00
.pointingNorth {
2025-06-19 15:41:07 +00:00
width: 236px;
height: 52px;
2025-04-13 08:23:44 +00:00
position: absolute;
2025-06-19 15:41:07 +00:00
bottom: 37px;
left: 50%;
transform: translateX(-50%);
2025-06-16 14:22:14 +00:00
z-index: 1000;
2025-06-19 15:41:07 +00:00
display: flex;
align-items: center;
justify-content: space-between;
2025-04-24 12:55:18 +00:00
img {
2025-06-19 15:41:07 +00:00
width: 52px;
height: 52px;
2025-04-24 12:55:18 +00:00
}
2025-04-13 08:23:44 +00:00
}
2025-03-31 15:26:29 +00:00
}
</style>