新增点击地点标点,弹出地点信息弹窗功能

master
qubiaobiao 2024-03-04 15:57:34 +08:00
parent e7d6b9ab9e
commit eed0aa1d50
70 changed files with 773 additions and 131 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 MiB

View File

@ -3,7 +3,10 @@
<Earth> <Earth>
<LocatingPoint /> <LocatingPoint />
<MarkPoints /> <MarkPoints />
<LandMarkPoints />
</Earth> </Earth>
<LandMarkWindow />
<LandMarkShow />
</vc-config-provider> </vc-config-provider>
<LonlatForm id="lonlat-form"></LonlatForm> <LonlatForm id="lonlat-form"></LonlatForm>
@ -19,6 +22,9 @@ import LonlatTable from '/@/components/LonlatTable.vue'
import MarkPoints from "/@/components/MarkPoints.vue" import MarkPoints from "/@/components/MarkPoints.vue"
import LocatingPoint from '/@/components/LocatingPoint.vue' import LocatingPoint from '/@/components/LocatingPoint.vue'
import HotLandmark from '/@/components/HotLandmark.vue' import HotLandmark from '/@/components/HotLandmark.vue'
import LandMarkPoints from "/@/components/LandMarkPoints.vue"
import LandMarkWindow from '/@/components/LandMarkWindow.vue'
import LandMarkShow from '/@/components/LandMarkShow.vue'
const CESIUM_PATH = (process.env.NODE_ENV === 'development' ? './node_modules/cesium/Build/Cesium/Cesium.js': './Cesium/Cesium.js') const CESIUM_PATH = (process.env.NODE_ENV === 'development' ? './node_modules/cesium/Build/Cesium/Cesium.js': './Cesium/Cesium.js')
</script> </script>

BIN
src/assets/button.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
src/assets/close.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 15 KiB

BIN
src/assets/left.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
src/assets/right.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
src/assets/showpin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
src/assets/todown.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
src/assets/toup.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,32 +1,32 @@
<template> <template>
<div class="compass" @click="Compass"> <div class="compass" style="cursor: pointer" @click="Compass">
<img class="north" src="../assets/compass.png"> <img class="north" src="../assets/compass.png" />
</div> </div>
</template> </template>
<script setup> <script setup>
import {defineEmits} from 'vue' import { defineEmits } from "vue";
const emit = defineEmits(['Pointing']) const emit = defineEmits(["Pointing"]);
const Compass = () => { const Compass = () => {
emit('Pointing') emit("Pointing");
} };
</script> </script>
<style scoped> <style scoped>
.compass{ .compass {
width:50px; width: 50px;
height:50px; height: 50px;
padding:5px; padding: 5px;
padding-top:0; padding-top: 0;
border-radius:50%; border-radius: 50%;
background-color:#fff; background-color: #fff;
position:fixed; position: fixed;
bottom:245px; bottom: 245px;
left:42px; left: 42px;
z-index:99; z-index: 99;
} }
.north{ .north {
width:40px; width: 40px;
} }
</style> </style>

View File

@ -1,10 +1,20 @@
<template> <template>
<div> <div>
<div v-show="!showit" class="switch" style="position:absolute;top:-40px;right:0;z-index:99;" @click="showLandmark"> <div
<img class="icon" src="../assets/up.png"> v-show="!showit"
class="switch"
style="position: absolute; top: -40px; right: 0; z-index: 99; cursor: pointer"
@click="showLandmark"
>
<img class="icon" src="../assets/toup.png" />
</div> </div>
<div v-show="showit" class="switch" style="position:absolute;top:-50px;right:0;z-index:99;" @click="showLandmark"> <div
<img class="icon" src="../assets/down.png"> v-show="showit"
class="switch"
style="position: absolute; top: -50px; right: 0; z-index: 99; cursor: pointer"
@click="showLandmark"
>
<img class="icon" src="../assets/todown.png" />
</div> </div>
<div class="landmark"> <div class="landmark">
<table v-if="showit"> <table v-if="showit">
@ -18,10 +28,12 @@
</thead> </thead>
<tbody> <tbody>
<tr v-for="(item, index) in landmarkArr" :key="index"> <tr v-for="(item, index) in landmarkArr" :key="index">
<td>{{ item ? item.landmark : index+1 }}</td> <td>{{ item ? item.landmark : index + 1 }}</td>
<td>{{ item ? item.lng : "" }}</td> <td>{{ item ? item.position.lng : "" }}</td>
<td>{{ item ? item.lat : "" }}</td> <td>{{ item ? item.position.lat : "" }}</td>
<td><button @click="write(item.lng,item.lat)">访</button></td> <td>
<button style="cursor: pointer" @click="write(item.position)">访</button>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -30,77 +42,50 @@
</template> </template>
<script setup> <script setup>
import { ref } from 'vue' import { ref } from "vue";
import { usePositionStore } from '/@/stores/position' import { usePositionStore } from "/@/stores/position";
import { landmarkArr } from "/@/information/landmark";
const landmarkArr = [
{
landmark:'北京天安门',
lng:116.391243,
lat:39.907202
},
{
landmark:'北京鸟巢',
lng:116.390502,
lat:39.991396
},
{
landmark:'上海东方明珠',
lng:121.495263,
lat:31.241829
},
{
landmark:'香港迪斯尼',
lng:114.042287,
lat:22.313002
},
{
landmark:'布达拉宫',
lng:91.117684,
lat:29.656959
}
]
let showit = ref(false); let showit = ref(false);
const showLandmark = () => { const showLandmark = () => {
showit.value = !showit.value; showit.value = !showit.value;
} };
const position = usePositionStore() const position = usePositionStore();
const write = (lng,lat) => { const write = (myposition) => {
position.set({ lng: lng, lat: lat }) position.set(myposition);
} };
</script> </script>
<style scoped> <style scoped>
.landmark { .landmark {
max-height: 360px; max-height: 360px;
overflow-y:scroll; overflow-y: scroll;
} }
.switch { .switch {
width:42px; width: 42px;
height:42px; height: 42px;
border-radius: 50%; border-radius: 50%;
background-color:#fff; background-color: #fff;
padding-top:9px; padding-top: 9px;
padding-left:3px; padding-left: 3px;
} }
.icon { .icon {
width:36px; width: 36px;
} }
table { table {
color: #FFFFFF; color: #ffffff;
background-color: #242424; background-color: #242424;
padding: 10px; padding: 10px;
border-radius: 7px; border-radius: 7px;
border-collapse: separate; border-collapse: separate;
border-spacing: 2px; border-spacing: 2px;
text-align:center; text-align: center;
} }
table th:first-child { table th:first-child {
@ -123,7 +108,8 @@ table tbody tr:nth-child(odd) {
background-color: rgba(84, 84, 84, 0.25); background-color: rgba(84, 84, 84, 0.25);
} }
table th, table td { table th,
table td {
padding: 3px 5px; padding: 3px 5px;
} }
</style> </style>

View File

@ -0,0 +1,16 @@
<template>
<Pin
v-for="item, index in landmarkArr"
:key="index"
:position="item.position"
:image="showpin"
:pintype="landmark"/>
</template>
<script setup>
import { landmarkArr } from '/@/information/landmark'
import Pin from '/@/components/Pin.vue'
import showpin from '/@/assets/showpin.png'
const landmark = "landmark"
</script>

View File

@ -0,0 +1,223 @@
<template>
<div class="lightbox" :style="judgmentShow">
<div class="boxImg">
<img :id="nowId" style="height:100%;display:block;margin:auto;" :src="nowImg" />
<div id="describesBox" class="describesBox" :style="describesShow">
<div class="textBox">
<br />
<h1 class="describesTitle">{{LandMarkShow.information.landTitle}}</h1>
<br />
<p class="describesParagraph">{{LandMarkShow.information.landDescribes}}</p>
</div>
</div>
<div id="brieflyBox" class="brieflyBox" :style="brieflyShow">
<div class="textBox">
<h3 class="brieflyTitle">{{LandMarkShow.information.landTitle}}</h3>
<p class="brieflyParagraph">{{LandMarkShow.information.landDescribes}}</p>
</div>
</div>
<div class="share showBtn">
<img class="imgBase" :style="judgmentUp" src="../../src/assets/up.png" @click="up" />
<img class="imgBase" :style="judgmentDown" src="../../src/assets/down.png" @click="down" />
</div>
<div class="share leftBtn">
<img class="imgBase" src="../../src/assets/left.png" @click="left" />
</div>
<div class="share rightBtn">
<img class="imgBase" src="../../src/assets/right.png" @click="right" />
</div>
</div>
<div class="share boxClose">
<img class="imgBase" src="../../src/assets/close.png" @click="close" />
</div>
</div>
</template>
<script setup>
import { LandMarkShowStore } from '/@/stores/LandMarkShow';
import { ref, watch } from 'vue';
const LandMarkShow = LandMarkShowStore();
const judgmentShow = ref();
const describesShow = ref();
const brieflyShow = ref();
const nowId = ref(1);
const nowImg = ref();
const judgmentUp = ref("dispaly:block;");
const judgmentDown = ref("dispaly:none;");
const adaptive = (imgId) => {
let newImg;
let describesBox;
let brieflyBox;
setTimeout(() => {
newImg = document.getElementById(imgId);
describesBox = document.getElementById("describesBox");
brieflyBox = document.getElementById("brieflyBox");
}, 5);
setTimeout(() => {
let newWidth = window.getComputedStyle(newImg, null)["width"];
let newMargin = window.getComputedStyle(newImg, null).marginLeft;
describesBox.style.width = newWidth;
describesBox.style.left = newMargin;
brieflyBox.style.width = newWidth;
brieflyBox.style.left = newMargin;
}, 10);
}
watch(() => LandMarkShow.boxShow, (newValue, oldValue) => {
judgmentShow.value = `display:${LandMarkShow.boxShow?'block':'none'};`;
})
watch(() => LandMarkShow.information.landImgUrl, (newValue, oldValue) => {
nowId.value = 1;
nowImg.value = `${LandMarkShow.information.landImgUrl}${nowId.value}.jpg`;
describesShow.value = "display:none;";
brieflyShow.value = "display:block;";
judgmentUp.value = "display:block;";
judgmentDown.value = "display:none;";
adaptive(nowId.value);
})
const up = () => {
describesShow.value = "display:block;";
brieflyShow.value = "display:none;";
judgmentUp.value = "display:none;";
judgmentDown.value = "display:block;";
adaptive(nowId.value);
}
const down = () => {
describesShow.value = "display:none;";
brieflyShow.value = "display:block;";
judgmentUp.value = "display:block;";
judgmentDown.value = "display:none;";
adaptive(nowId.value);
}
const left = () => {
nowId.value = nowId.value - 1;
if (nowId.value == 0) {
nowId.value = LandMarkShow.information.landImgCount;
}
nowImg.value = `${LandMarkShow.information.landImgUrl}${nowId.value}.jpg`;
adaptive(nowId.value);
}
const right = () => {
nowId.value = nowId.value + 1;
if (nowId.value > LandMarkShow.information.landImgCount) {
nowId.value = 1;
}
nowImg.value = `${LandMarkShow.information.landImgUrl}${nowId.value}.jpg`;
adaptive(nowId.value);
}
const close = () => {
LandMarkShow.boxShow = false;
}
</script>
<style scoped>
.lightbox {
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.4);
position: absolute;
top: 0;
left: 0;
user-select: none;
display:none;
}
.boxImg {
width: 70%;
height: 50%;
position: absolute;
top: 20%;
left: 15%;
}
.imgBase {
width: 100%;
}
.share {
min-width: 32px;
min-height: 32px;
width: 3vw;
height: 3vw;
position: absolute;
bottom: 0;
z-index: 1;
border-radius: 50%;
overflow: hidden;
cursor: pointer;
box-shadow:inset 0px 0px 6px white;
}
.describesBox {
width: 60%;
height: 100%;
background: rgba(255, 255, 255, 0.5);
position: absolute;
bottom: 0;
left: 20%;
display: none;
text-shadow: 0 0 6px white;
}
.brieflyBox {
width: 60%;
height: 30%;
background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.8));
position: absolute;
bottom: 0;
left: 20%;
text-shadow: 0 0 6px black;
}
.textBox {
width: 80%;
height: 90%;
overflow: hidden;
margin: auto;
}
.describesTitle {
text-align: center;
margin: 0;
font-size: clamp(0.8rem, 0.489rem + 1.05vw, 2rem);
}
.describesParagraph {
text-align: left;
text-indent: 2em;
margin: 0;
font-size: clamp(0.5rem, 0.489rem + 1.05vw, 1rem);
}
.brieflyTitle {
color: #fff;
text-align: left;
margin: 0;
font-size: clamp(0.6rem, 0.489rem + 1.05vw, 1.2rem);
}
.brieflyParagraph {
color: #fff;
font-size: clamp(0.4rem, 0.489rem + 1.05vw, 0.8rem);
text-align: left;
text-indent: 2em;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 3;
display: -webkit-box;
-webkit-box-orient: vertical;
}
.boxClose {
bottom: 20%;
left: 48.5%;
}
.showBtn {
bottom: 0;
left: 47.8%;
}
.leftBtn {
left: 40%;
}
.rightBtn {
right: 40%;
}
</style>

View File

@ -0,0 +1,132 @@
<template>
<div class="window" :style="nowPosition">
<div class="base">
<div>{{LandMarkWindow.information.landTitle}}</div>
<div class="triangle"></div>
<div class="backimg" :style="nowImg">{{LandMarkWindow.information.landTitle}}</div>
</div>
<div class="closeBtn" @click="closeWindow">
<svg
t="1603334792546"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="1328"
width="20"
height="20"
>
<path
d="M568.922 508.232L868.29 208.807a39.139 39.139 0 0 0 0-55.145l-1.64-1.64a39.139 39.139 0 0 0-55.09 0l-299.367 299.82-299.425-299.934a39.139 39.139 0 0 0-55.088 0l-1.697 1.64a38.46 38.46 0 0 0 0 55.09l299.48 299.594-299.424 299.48a39.139 39.139 0 0 0 0 55.09l1.64 1.696a39.139 39.139 0 0 0 55.09 0l299.424-299.48L811.56 864.441a39.139 39.139 0 0 0 55.089 0l1.696-1.64a39.139 39.139 0 0 0 0-55.09l-299.48-299.537z"
p-id="1329"
></path>
</svg>
</div>
<div class="changeButton" @click="judgment">{{LandMarkWindow.buttonText?'':''}}</div>
</div>
</template>
<script setup>
import { LandMarkWindowStore } from '/@/stores/LandMarkWindow';
import { LandMarkShowStore } from '/@/stores/LandMarkShow';
import { ref, watch } from 'vue';
const LandMarkWindow = LandMarkWindowStore();
const LandMarkShow = LandMarkShowStore();
const nowPosition = ref();
const nowImg = ref();
watch(() => LandMarkWindow.windowShow, (newValue, oldValue) => {
nowPosition.value = `bottom:${LandMarkWindow.windowPosition.bottom};left:${LandMarkWindow.windowPosition.left};display:${LandMarkWindow.windowShow?'block':'none'};`;
})
watch(() => LandMarkWindow.information.landImgUrl, (newValue, oldValue) => {
nowImg.value = `background-image: url('${LandMarkWindow.information.landImgUrl}1.jpg');`;
})
watch(() => LandMarkWindow.windowPosition.left, (newValue, oldValue) => {
nowPosition.value = `bottom:${LandMarkWindow.windowPosition.bottom};left:${LandMarkWindow.windowPosition.left};display:${LandMarkWindow.windowShow?'block':'none'};`;
})
const closeWindow = () => {
LandMarkWindow.windowShow = false;
LandMarkWindow.hiddenWindow = true;
}
const flyToLandmark = () => {
LandMarkWindow.flyToLand = true;
}
const watchImg = () => {
LandMarkShow.boxShow = true;
LandMarkShow.information = LandMarkWindow.information;
}
const judgment = () => {
if(LandMarkWindow.buttonText){
watchImg()
}else{
flyToLandmark()
}
}
</script>
<style scoped>
.window {
width: 300px;
height: 30px;
position: absolute;
display:none;
}
.base {
background: #FFFFA0;
height: 200px;
text-align: center;
}
.triangle {
width: 0;
height: 0;
border-top: 10px solid red;
border-right: 10px solid transparent;
border-left: 10px solid transparent;
position: absolute;
left: 140px;
bottom: -200px;
}
.backimg {
color: red;
text-shadow: 0px 0px 8px rgba(255, 255, 255, 0.5);
padding-top: 4px;
font-size: 32px;
background-size: cover;
height: 200px;
line-height:100px;
border-radius: 0px 0px 10px 10px;
}
.closeBtn {
width:20px;
height:21px;
position:absolute;
top:0;
right:0;
background-color:#fff;
cursor:pointer;
}
.closeBtn:hover {
background-color: red;
}
.changeButton {
width:110px;
height:40px;
position:absolute;
top:100px;
right:95px;
background-image:url('../../src/assets/button.png');
background-size:cover;
color:#fff;
border:1px solid skyblue;
border-radius:16px;
box-shadow:0px 0px 8px skyblue;
text-align:center;
line-height:36px;
cursor:pointer;
}
</style>

View File

@ -1,37 +1,45 @@
<template> <template>
<form @keyup.enter="onFlyBtnClick"> <form @keyup.enter="onFlyBtnClick">
<label>经度</label> <label>经度</label>
<input type="number" v-model="lng" placeholder="请输入经度值"> <input type="number" v-model="lng" placeholder="请输入经度值" />
<label>纬度</label> <label>纬度</label>
<input type="number" v-model="lat" placeholder="请输入纬度值"> <input type="number" v-model="lat" placeholder="请输入纬度值" />
<input type="button" id="fly-btn" @click="onFlyBtnClick" value="飞到这个点"> <input
<input type="button" id="clear-btn" @click="onClearBtnClick" value="清除坐标"> type="button"
style="cursor: pointer"
id="fly-btn"
@click="onFlyBtnClick"
value="飞到这个点"
/>
<input
type="button"
style="cursor: pointer"
id="clear-btn"
@click="onClearBtnClick"
value="清除坐标"
/>
</form> </form>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref } from "vue";
import { usePointStore } from '/@/stores/point' import { usePointStore } from "/@/stores/point";
import { usePositionStore } from '/@/stores/position' import { usePositionStore } from "/@/stores/position";
const lng = ref(NaN) const lng = ref(NaN);
const lat = ref(NaN) const lat = ref(NaN);
const position = usePositionStore() const position = usePositionStore();
const onFlyBtnClick = () => { const onFlyBtnClick = () => {
if ( !position.set({ lng: lng.value, lat: lat.value }) ) alert('请输入正确的经纬度信息') if (!position.set({ lng: lng.value, lat: lat.value })) alert("请输入正确的经纬度信息");
} };
const point = usePointStore();
const point = usePointStore()
const onClearBtnClick = () => { const onClearBtnClick = () => {
lng.value = NaN lng.value = NaN;
lat.value = NaN lat.value = NaN;
position.$reset() position.$reset();
point.$reset() point.$reset();
} };
</script> </script>
<style scoped> <style scoped>
@ -63,25 +71,26 @@ input:focus {
} }
/* Chrome, Safari, Edge, Opera */ /* Chrome, Safari, Edge, Opera */
input[type=number]::-webkit-outer-spin-button, input[type="number"]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button { input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none; -webkit-appearance: none;
margin: 0; margin: 0;
} }
/* Firefox */ /* Firefox */
input[type=number] { input[type="number"] {
-moz-appearance: textfield; -moz-appearance: textfield;
} }
input#fly-btn, input#clear-btn { input#fly-btn,
input#clear-btn {
border-radius: 3px; border-radius: 3px;
background-color: #41ddee; background-color: #41ddee;
} }
input#fly-btn:hover , input#clear-btn:hover { input#fly-btn:hover,
input#clear-btn:hover {
background-color: #ffffff; background-color: #ffffff;
color: #41ddee; color: #41ddee;
} }
</style> </style>

View File

@ -1,14 +1,30 @@
<template> <template>
<vc-entity :show="show" :position="position"> <vc-entity
<vc-graphics-billboard :image="image" :verticalOrigin="1" /> :show="pintype == 'landmark' ? landshow : show"
:position="position"
@click="clickPin"
@ready="ready"
>
<vc-graphics-billboard
:image="image"
:verticalOrigin="1"
:scale="pintype == 'landmark' ? jump : 1"
:color="pintype == 'landmark' ? jumpColor : 'none'"
/>
</vc-entity> </vc-entity>
</template> </template>
<script setup> <script setup>
import { computed } from 'vue' import { LandMarkWindowStore } from '/@/stores/LandMarkWindow';
import { VcEntity, VcGraphicsBillboard } from 'vue-cesium' import { LandMarkShowStore } from '/@/stores/LandMarkShow';
import { isLnglat } from '/@/api/util' import { ref, computed, watch } from "vue";
import pin from '/@/assets/pin.png' import { VcEntity, VcGraphicsBillboard } from "vue-cesium";
import { isLnglat } from "/@/api/util";
import { landmarkArr } from "/@/information/landmark";
import pin from "/@/assets/pin.png";
const LandMarkWindow = LandMarkWindowStore();
const LandMarkShow = LandMarkShowStore();
const props = defineProps({ const props = defineProps({
position: { position: {
@ -18,8 +34,155 @@ const props = defineProps({
image: { image: {
type: String, type: String,
default: pin, default: pin,
},
pintype: {
type: String,
default: "ordinary",
},
});
const show = computed(() => isLnglat(props.position));
const landshow = ref(false);
const jump = ref(1);
const jumpSwitch = ref(true);
const jumpColor = ref("none");
let Cesium = null,
viewer = null,
handler = null;
const animetion = () => {
setInterval(() => {
if (0.5 <= jump.value < 1.1 && jumpSwitch.value) {
jump.value = Math.round(jump.value * 100) / 100 + 0.05;
jumpColor.value = "none";
if (jump.value == 1.1) {
jumpSwitch.value = false;
jumpColor.value = "rgba(0,255,255,0.5)";
}
} else if (0.5 < jump.value <= 1.1) {
jump.value = Math.round(jump.value * 100) / 100 - 0.05;
jumpColor.value = "none";
if (jump.value == 0.5) {
jumpSwitch.value = true;
jumpColor.value = "rgba(0,255,255,0.5)";
}
}
}, 100);
};
const ready = (readyObj) => {
Cesium = readyObj.Cesium;
viewer = readyObj.viewer;
handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
viewer.scene.postRender.addEventListener(() => {
if (viewer.camera.positionCartographic.height < 100000) {
landshow.value = true;
} else {
landshow.value = false;
}
});
if (props.pintype == "landmark") {
animetion();
}
};
let landTitle, landDescribes, landImgUrl, landPosition, landImgCount;
const insetLand = () => {
landmarkArr.forEach((element) => {
if (
element.position.lng == props.position.lng &&
element.position.lat == props.position.lat
) {
landTitle = element.landmark;
landDescribes = element.describes;
landImgUrl = element.imgUrl;
landPosition = element.position;
landImgCount = element.imgCount;
}
});
}
const clearDiv = (id) => {
viewer.scene.postRender.removeEventListener(addDynamicLabel);
handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
};
const addDynamicLabel = (data) => {
insetLand();
LandMarkWindow.information.landTitle = landTitle;
LandMarkWindow.information.landDescribes = landDescribes;
LandMarkWindow.information.landImgUrl = landImgUrl;
LandMarkWindow.information.landPosition = landPosition;
LandMarkWindow.information.landImgCount = landImgCount;
LandMarkWindow.windowShow = true;
LandMarkWindow.hiddenWindow = false;
let gisPosition = data.position._value;
viewer.scene.postRender.addEventListener(() => {
const canvasHeight = viewer.scene.canvas.height;
const windowPosition = new Cesium.Cartesian2();
Cesium.SceneTransforms.wgs84ToWindowCoordinates(
viewer.scene,
gisPosition,
windowPosition
);
// LandMarkWindow
const elWidth = 300;
let showBottom = canvasHeight - windowPosition.y + 240 + "px";
let showLeft = windowPosition.x - elWidth / 2 + "px";
LandMarkWindow.windowPosition.bottom = showBottom;
LandMarkWindow.windowPosition.left = showLeft;
const camerPosition = viewer.camera.position;
let height = viewer.scene.globe.ellipsoid.cartesianToCartographic(camerPosition).height;
height += viewer.scene.globe.ellipsoid.maximumRadius;
if (viewer.camera.positionCartographic.height < 2400) {
LandMarkWindow.buttonText = true;
} else {
LandMarkWindow.buttonText = false;
}
if (viewer.camera.positionCartographic.height > 100000) {
LandMarkWindow.windowShow = false;
}else{
if(!LandMarkWindow.hiddenWindow){
LandMarkWindow.windowShow = true;
}
}
});
handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.setInputAction(function (movement) {
LandMarkWindow.windowShow = false;
LandMarkWindow.hiddenWindow = true;
clearDiv();
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
};
watch(() => LandMarkWindow.flyToLand, (newValue, oldValue) => {
if(LandMarkWindow.flyToLand){
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(
LandMarkWindow.information.landPosition.lng,
LandMarkWindow.information.landPosition.lat,
2000.0
),
});
LandMarkWindow.flyToLand = false;
} }
}) })
const show = computed(() => isLnglat(props.position)) const clickPin = () => {
if (props.pintype == "landmark") {
handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.setInputAction(function (movement) {
let pick = viewer.scene.pick(movement.position);
if (Cesium.defined(pick) && pick.id.id) {
let id = pick.id.id;
let entiy = viewer.entities.getById(id);
addDynamicLabel(entiy);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
};
</script> </script>

View File

@ -0,0 +1,68 @@
export const landmarkArr = [
{
landmark:'北京天安门',
position:{
lng:116.391243,
lat:39.907202
},
describes:`天安门Tian'anmen坐落在中华人民共和国首都北京市的中心、故宫的南端与天安门广场以及人民英雄纪念碑、毛主席纪念堂、人民大会堂、中国国家博物馆隔长安街相望占地面积4800平方米以杰出的建筑艺术和特殊的政治地位为世人所瞩目。
天安门是明清两代北京皇城的正门始建于明朝永乐十五年1417最初名承天门承天启运受命于天之意设计者为明代御用建筑匠师蒯祥清朝顺治八年1651更名为天安门由城台和城楼两部分组成有汉白玉石的须弥座总高34.7天安门城楼长66米宽37米城台下有券门五阙中间的券门最大位于北京市皇城中轴线上过去只有皇帝才可以由此出入正中门洞上方悬挂着毛泽东画像两边分别是中华人民共和国万岁世界人民大团结万岁的大幅标语
1925年10月10日故宫博物院成立天安门开始对民众开放1949年10月1日在这里举行了中华人民共和国开国大典由此被设计入国徽并成为中华人民共和国的象征1961中华人民共和国国务院公布为第一批全国重点文物保护单位之一`,
imgUrl:'/landmarkImg/TianAnmen/',
imgCount:8
},
{
landmark:'北京鸟巢',
position:{
lng:116.390502,
lat:39.991396
},
describes:`国家体育场National Stadium又名“鸟巢”Bird's Nest位于北京奥林匹克公园中心区南部为2008年北京奥运会的主体育场举行了2008年夏季奥运会、残奥会开闭幕式、田径比赛及足球比赛决赛以及2022年冬季奥运会、冬残奥会开闭幕式。
体育场占地20.4万平方米建筑面积25.8万平方米可容纳观众9.1万人其中正式座位8万个临时座位1.1万个由雅克·赫尔佐格德梅隆艾未未以及李兴钢等设计由北京城建集团负责施工体育场的形态如同孕育生命的和摇篮寄托着人类对未来的希望设计者们对这个场馆没有做任何多余的处理把结构暴露在外因而自然形成了建筑的外观
2003年12月24日开工建设2008年3月完工总造价22.67亿元作为国家标志性建筑2008年奥运会主体育场国家体育场结构特点十分显著体育场为特级体育建筑大型体育场馆主体结构设计使用年限100年耐火等级为一级抗震设防烈度8度地下工程防水等级1级2008年奥运会后国家体育场成为北京市民参与体育活动及享受体育娱乐的大型专业场所并成为地标性的体育建筑和奥运遗产`,
imgUrl:'/landmarkImg/BirdsNest/',
imgCount:8
},
{
landmark:'上海东方明珠',
position:{
lng:121.495263,
lat:31.241829
},
describes:`东方明珠广播电视塔简称“东方明珠”Oriental Pearl位于上海市浦东新区陆家嘴世纪大道1号地处黄浦江畔背拥陆家嘴地区现代化建筑楼群与隔江的外滩万国建筑博览群交相辉映1991年7月30日动工建造1994年10月1日建成投入使用是集都市观光、时尚餐饮、购物娱乐、历史陈列、浦江游览、会展演出、广播电视发射等多功能于一体的上海市标志性建筑之一。截至2019年为亚洲第六高塔、世界第九高塔。东方明珠广播电视塔主体为多筒结构由3根斜撑、3根立柱及广场、塔座、下球体、5个小球体、上球体、太空舱、发射天线桅杆等构成总高468米总建筑面积达10万平方米。1995年东方明珠广播电视塔被评为上海十大新景观之一。1999年东方明珠广播电视塔获上海市优秀勘察设计一等奖、中国土木工程詹天佑奖。2007年5月8日东方明珠广播电视塔被中华人民共和国国家旅游局批准为国家AAAAA级旅游景区。`,
imgUrl:'/landmarkImg/OrientalPearl/',
imgCount:8
},
{
landmark:'香港迪士尼',
position:{
lng:114.042287,
lat:22.313002
},
describes:`香港迪士尼乐园Hong Kong Disneyland位于中华人民共和国香港特别行政区新界大屿山占地126公顷在2005年9月12日正式开幕由香港特别行政区政府以及华特迪士尼公司联合经营的香港国际主题乐园有限公司建设及营运是全球第五座、亚洲第二座、中国第一座迪士尼乐园。乐园分为9个主题园区分别为美国小镇大街、探险世界、幻想世界、明日世界、灰熊山谷、铁甲奇侠总部、反斗奇兵大本营、迷离庄园、魔雪奇缘世界其中灰熊山谷和迷离庄园为全球独有。园区内设有主题游乐设施、娱乐表演、互动体验、餐饮服务、商品店铺及小食亭。此外乐园每天晚上会呈献巡游表演节目及烟花汇演。2022年10月基建咨询服务企业AECOM联合主题娱乐协会TEA发布了《2021全球主题公园和博物馆报告》香港迪士尼乐园入选全球主题公园Top25排行榜第21名亚太地区Top 20主题乐园排行榜第10名。`,
imgUrl:'/landmarkImg/HongKongDisneyland/',
imgCount:8
},
{
landmark:'布达拉宫',
position:{
lng:91.117684,
lat:29.656959
},
describes:`布达拉宫Potala Palace位于中国西藏自治区首府拉萨市区西北的玛布日山上是一座宫堡式建筑群一说为吐蕃王朝赞普松赞干布为迎娶尺尊公主和文成公主而兴建另一说为作为松赞干布迁都拉萨后的王宫而建。于17世纪重建后成为历代达赖喇嘛的冬宫居所为西藏政教合一的统治中心。
布达拉宫的主体建筑为白宫和红宫两部分整座宫殿具有藏式风格外观13层实际只有9层由于它起建于山腰大面积的石壁又屹立如峭壁使建筑仿佛与山岗融为一体气势雄伟布达拉宫海拔3700米占地总面积36万平方米建筑总面积13万平方米由东部的白宫中部的红宫组成主楼高117米布达拉宫主体建筑的东西两侧分别向下延伸与高大的宫墙相接宫墙高6米底宽4.4顶宽2.8用夯土砌筑外包砖石墙的东西侧各有一座三层的门楼在东南和西北角还各有一座角楼宫墙所包围的范围全都属于布达拉宫
布达拉宫的壁画木雕及建筑过程中使用的金属冶炼技术均闻名于世体现了以藏族为主满各族能工巧匠高超的技艺1961布达拉宫成为了中华人民共和国国务院第一批全国重点文物保护单位之一1994布达拉宫被列为世界文化遗产`,
imgUrl:'/landmarkImg/PotalaPalace/',
imgCount:8
},
{
landmark:'西昌卫星发射中心',
position:{
lng:102.026661,
lat:28.245627
},
describes:`西昌卫星发射中心英文Xichang Satellite Launch Center简称XSLC又称“西昌卫星城”是中国卫星发射基地之一。组建于1970年是中国三大航天发射中心之一管理使用西昌、文昌两个航天发射场。西昌发射场1982年交付使用位于四川省凉山彝族自治州冕宁县。西昌发射场地处山区是全球十大发射场中气候条件最为复杂的发射场之一。`,
imgUrl:'/landmarkImg/XichangSatelliteLaunchCenter/',
imgCount:9
}
]

View File

@ -0,0 +1,16 @@
import { defineStore } from 'pinia'
export const LandMarkShowStore = defineStore({
id: 'LandMarkShow',
state: () => ({
information: {
landTitle: NaN,
landDescribes: NaN,
landImgUrl: NaN,
landPosition: NaN,
landImgCount: NaN
},
boxShow: false,
})
})

View File

@ -0,0 +1,23 @@
import { defineStore } from 'pinia'
export const LandMarkWindowStore = defineStore({
id: 'LandMarkWindow',
state: () => ({
information: {
landTitle: NaN,
landDescribes: NaN,
landImgUrl: NaN,
landPosition: NaN,
landImgCount: NaN
},
windowPosition: {
bottom: NaN,
left: NaN
},
buttonText: false,
windowShow: false,
hiddenWindow: false,
flyToLand: false,
})
})