|
@@ -0,0 +1,246 @@
|
|
|
|
+<template>
|
|
|
|
+ <div class="map-view">
|
|
|
|
+ <button class="back" @click="router.go(-1)"></button>
|
|
|
|
+ <button
|
|
|
|
+ ref="poiButtonElList"
|
|
|
|
+ class="poi-icon"
|
|
|
|
+ v-for="(item, idx) in poiList"
|
|
|
|
+ :key="item.name"
|
|
|
|
+ :style="{
|
|
|
|
+ left: item.posOnMapPage.left,
|
|
|
|
+ top: item.posOnMapPage.top,
|
|
|
|
+ }"
|
|
|
|
+ @click="activePoiIdx = idx"
|
|
|
|
+ ></button>
|
|
|
|
+ <transition name="fade-in">
|
|
|
|
+ <div class="poi-info-dialog" v-if="activePoiIdx !== null" ref="dialogEl">
|
|
|
|
+ <div ref="arrowEl" class="arrow" />
|
|
|
|
+ <div class="top-bar">
|
|
|
|
+ <button class="locate" @click="onClickLocateBtn">
|
|
|
|
+ <img
|
|
|
|
+ class=""
|
|
|
|
+ src="@/assets/images/icon-locate.png"
|
|
|
|
+ alt=""
|
|
|
|
+ draggable="false"
|
|
|
|
+ />
|
|
|
|
+ </button>
|
|
|
|
+ <button class="close" @click="activePoiIdx = null">
|
|
|
|
+ <img
|
|
|
|
+ class=""
|
|
|
|
+ src="@/assets/images/icon-close.png"
|
|
|
|
+ alt=""
|
|
|
|
+ draggable="false"
|
|
|
|
+ />
|
|
|
|
+ </button>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="content-wrap">
|
|
|
|
+ <img
|
|
|
|
+ class="photo"
|
|
|
|
+ :src="
|
|
|
|
+ require(`@/assets/images/poiImages/${activePoiPhotoName}.jpg`)
|
|
|
|
+ "
|
|
|
|
+ alt=""
|
|
|
|
+ draggable="false"
|
|
|
|
+ />
|
|
|
|
+ <h3>{{ activePoiName }}</h3>
|
|
|
|
+ <div class="text-wrap">
|
|
|
|
+ <p
|
|
|
|
+ v-for="(item, index) in characterText"
|
|
|
|
+ :key="index"
|
|
|
|
+ v-html="item"
|
|
|
|
+ ></p>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </transition>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script setup>
|
|
|
|
+import {
|
|
|
|
+ ref,
|
|
|
|
+ computed,
|
|
|
|
+ watch,
|
|
|
|
+ // onMounted,
|
|
|
|
+ // inject
|
|
|
|
+} from "vue";
|
|
|
|
+import { useRouter } from "vue-router";
|
|
|
|
+// import { useStore } from "vuex"
|
|
|
|
+import { poiList } from "@/config.js";
|
|
|
|
+import { computePosition, offset, flip, shift, arrow } from "@floating-ui/dom";
|
|
|
|
+
|
|
|
|
+// const route = useRoute()
|
|
|
|
+const router = useRouter();
|
|
|
|
+// const store = useStore()
|
|
|
|
+
|
|
|
|
+// const $env = inject('$env')
|
|
|
|
+
|
|
|
|
+const poiButtonElList = ref([]);
|
|
|
|
+const dialogEl = ref(null);
|
|
|
|
+const arrowEl = ref(null);
|
|
|
|
+
|
|
|
|
+const activePoiIdx = ref(null);
|
|
|
|
+const activePoiPhotoName = computed(() => {
|
|
|
|
+ return poiList[activePoiIdx.value]?.name;
|
|
|
|
+});
|
|
|
|
+const activePoiName = computed(() => {
|
|
|
|
+ return poiList[activePoiIdx.value]?.name;
|
|
|
|
+});
|
|
|
|
+const characterText = computed(() => {
|
|
|
|
+ return poiList[activePoiIdx.value]?.text;
|
|
|
|
+});
|
|
|
|
+watch(activePoiIdx, (v) => {
|
|
|
|
+ if (v === null) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ computePosition(poiButtonElList.value[v], dialogEl.value, {
|
|
|
|
+ placement: "top",
|
|
|
|
+ middleware: [
|
|
|
|
+ offset(10),
|
|
|
|
+ flip(),
|
|
|
|
+ shift({ padding: 10 }),
|
|
|
|
+ arrow({
|
|
|
|
+ element: arrowEl.value,
|
|
|
|
+ padding: 5,
|
|
|
|
+ }),
|
|
|
|
+ ],
|
|
|
|
+ }).then(({ x, y, placement, middlewareData }) => {
|
|
|
|
+ Object.assign(dialogEl.value.style, {
|
|
|
|
+ left: `${x}px`,
|
|
|
|
+ top: `${y}px`,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const { x: arrowX } = middlewareData.arrow;
|
|
|
|
+ const arrowPlacement = {
|
|
|
|
+ top: "bottom",
|
|
|
|
+ right: "left",
|
|
|
|
+ bottom: "top",
|
|
|
|
+ left: "right",
|
|
|
|
+ }[placement.split("-")[0]];
|
|
|
|
+ const dialogPlacement2arrowRotate = {
|
|
|
|
+ top: "-135deg",
|
|
|
|
+ right: "-45deg",
|
|
|
|
+ bottom: "45deg",
|
|
|
|
+ left: "135deg",
|
|
|
|
+ };
|
|
|
|
+ Object.assign(arrowEl.value.style, {
|
|
|
|
+ top: "initial",
|
|
|
|
+ bottom: "initial",
|
|
|
|
+ left: "initial",
|
|
|
|
+ right: "initial",
|
|
|
|
+ });
|
|
|
|
+ Object.assign(arrowEl.value.style, {
|
|
|
|
+ left: arrowX != null ? `${arrowX}px` : "",
|
|
|
|
+ [arrowPlacement]: -6 + "px",
|
|
|
|
+ transform: `rotate(${dialogPlacement2arrowRotate[placement]})`,
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ }, 0);
|
|
|
|
+});
|
|
|
|
+
|
|
|
|
+function onClickLocateBtn() {
|
|
|
|
+ window.messageCenter.publish("nav-to-poi", activePoiIdx.value);
|
|
|
|
+ router.push(`/`);
|
|
|
|
+}
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<style lang="less" scoped>
|
|
|
|
+.map-view {
|
|
|
|
+ pointer-events: initial;
|
|
|
|
+ position: absolute;
|
|
|
|
+ left: 0;
|
|
|
|
+ top: 0;
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 100%;
|
|
|
|
+ background-image: url(@/assets/images/map.png);
|
|
|
|
+ background-size: 100% auto;
|
|
|
|
+ background-repeat: no-repeat;
|
|
|
|
+ background-position: center center;
|
|
|
|
+ background-color: #fff;
|
|
|
|
+ > button.back {
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 33px;
|
|
|
|
+ left: 20px;
|
|
|
|
+ width: 50px;
|
|
|
|
+ height: 50px;
|
|
|
|
+ background-image: url(@/assets/images/btn-back.png);
|
|
|
|
+ background-size: cover;
|
|
|
|
+ background-repeat: no-repeat;
|
|
|
|
+ background-position: center center;
|
|
|
|
+ }
|
|
|
|
+ > button.poi-icon {
|
|
|
|
+ position: absolute;
|
|
|
|
+ width: 30px;
|
|
|
|
+ height: 30px;
|
|
|
|
+ background-image: url(@/assets/images/poi-icon-in-map.png);
|
|
|
|
+ background-size: contain;
|
|
|
|
+ background-repeat: no-repeat;
|
|
|
|
+ background-position: center center;
|
|
|
|
+ transform: translate(-50%, -55%);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ > .poi-info-dialog {
|
|
|
|
+ position: absolute;
|
|
|
|
+ width: 30.4vh;
|
|
|
|
+ height: 47.6%;
|
|
|
|
+ background-color: rgba(0, 0, 0, 0.7);
|
|
|
|
+ border-radius: 1vh;
|
|
|
|
+ padding-top: calc(0.07vh + 6.08vh + 2vh);
|
|
|
|
+ padding-left: 2vh;
|
|
|
|
+ padding-right: 2vh;
|
|
|
|
+ padding-bottom: 2vh;
|
|
|
|
+ > .arrow {
|
|
|
|
+ position: absolute;
|
|
|
|
+ width: 0;
|
|
|
|
+ height: 0;
|
|
|
|
+ border-left: solid 6px rgba(0, 0, 0, 0.7);
|
|
|
|
+ border-top: solid 6px rgba(0, 0, 0, 0.7);
|
|
|
|
+ border-right: solid 6px transparent;
|
|
|
|
+ border-bottom: solid 6px transparent;
|
|
|
|
+ }
|
|
|
|
+ > .top-bar {
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 0;
|
|
|
|
+ right: 0;
|
|
|
|
+ height: 6.08vh;
|
|
|
|
+ width: 19.02vh;
|
|
|
|
+ padding-right: 1vh;
|
|
|
|
+ display: flex;
|
|
|
|
+ justify-content: flex-end;
|
|
|
|
+ align-items: center;
|
|
|
|
+ gap: 2vh;
|
|
|
|
+ background: linear-gradient(90deg, rgba(153, 153, 153, 0) 0%, #999 100%);
|
|
|
|
+ border-radius: 3.07vh 1.18vh 0px 0px;
|
|
|
|
+ > img {
|
|
|
|
+ width: 1.2vw;
|
|
|
|
+ height: 1.2vw;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .content-wrap {
|
|
|
|
+ height: 100%;
|
|
|
|
+ overflow-y: auto;
|
|
|
|
+ > img.photo {
|
|
|
|
+ width: 100%;
|
|
|
|
+ }
|
|
|
|
+ > h3 {
|
|
|
|
+ font-family: Microsoft YaHei-Bold;
|
|
|
|
+ font-weight: bold;
|
|
|
|
+ text-align: center;
|
|
|
|
+ font-size: 16px;
|
|
|
|
+ line-height: 26px;
|
|
|
|
+ color: #fff;
|
|
|
|
+ margin-bottom: 0.5em;
|
|
|
|
+ }
|
|
|
|
+ > .text-wrap {
|
|
|
|
+ width: 100%;
|
|
|
|
+ font-family: Microsoft YaHei, Microsoft YaHei;
|
|
|
|
+ font-weight: 400;
|
|
|
|
+ font-size: 14px;
|
|
|
|
+ color: #fff;
|
|
|
|
+ line-height: 1.8;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+</style>
|