title.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. <template>
  2. <div class="header" @touchmove.prevent v-if="!isPanoramaMode">
  3. <div class="left" :class="{ show: !isTourMode }">
  4. <div v-show="!isPanoramaMode" class="back-pano" @click="onChangeMode">
  5. <i
  6. class="iconfont ui-kankan-icon icon tip-h-center tip-v-bottom icon-show_back iconzm-show_back"
  7. ></i>
  8. </div>
  9. <div v-show="isPanoramaMode" class="back" @click="onBack">
  10. <i
  11. class="iconfont ui-kankan-icon icon tip-h-center tip-v-bottom icon-_back iconzm-_back"
  12. ></i>
  13. </div>
  14. </div>
  15. <div
  16. class="title"
  17. :class="{
  18. up: player.showDescription,
  19. dark: !isPanoramaMode,
  20. empty: !description,
  21. }"
  22. @click="onShowDescription"
  23. v-show="player.showWidgets"
  24. >
  25. <div>
  26. <span>
  27. {{ metadata.title }}
  28. <i class="iconfont icon-pull-down"></i>
  29. </span>
  30. </div>
  31. </div>
  32. <div class="right" v-show="player.showWidgets" @click="onShowMore">
  33. <i class="iconfont icon-show_more_share"></i>
  34. </div>
  35. <transition
  36. appear
  37. name="custom-classes-transition"
  38. enter-active-class="animated fadeInUp short faster"
  39. leave-active-class="animated fadeOutDown short faster"
  40. >
  41. <div
  42. class="content"
  43. :class="{ dark: !isPanoramaMode }"
  44. v-if="player.showDescription"
  45. @click="onShowDescription"
  46. >
  47. <div>
  48. <div v-html="description"></div>
  49. </div>
  50. </div>
  51. </transition>
  52. <teleport to="body">
  53. <div class="url-share" v-show="showCopy" @click="showCopy = false">
  54. <img :src="shareImage" alt="" />
  55. </div>
  56. </teleport>
  57. </div>
  58. </template>
  59. <script setup lang="ts">
  60. //@ts-nocheck
  61. import browser from '/@/utils/browser';
  62. // import { useStore } from "vuex";
  63. // import { Dialog } from "@/global_components/";
  64. // import { useMusicPlayer } from "@/utils/sound";
  65. import { onMounted, watch, computed, ref, nextTick } from 'vue';
  66. import shareImage from '/@/assets/share.png';
  67. import { useAppStore } from '/@/store/modules/app';
  68. import { useSceneStore } from '/@/store/modules/scene';
  69. // import { useApp, getApp } from "@/app";
  70. const appStore = useAppStore();
  71. const sceneStore = useSceneStore();
  72. let share_url = browser.getURLParam('share_url');
  73. if (share_url) {
  74. share_url = decodeURIComponent(share_url);
  75. } else {
  76. share_url = `${location.origin}${location.pathname}?m=${browser.getURLParam('m')}`;
  77. }
  78. const isTourMode = computed(() => appStore.isTourMode);
  79. // const musicPlayer = useMusicPlayer()
  80. // const store = useStore();
  81. const metadata = computed(() => sceneStore.metadata);
  82. // const controls = computed(() => {
  83. // return sceneStore.metadata.controls;
  84. // });
  85. // const showMusicPlaying = ref(false);
  86. // const showMusic = computed(() => sceneStore.metadata.music);
  87. const player = computed(() => appStore.player);
  88. // const copy$ = ref(null);
  89. // const copyLink = ref(share_url);
  90. const showCopy = ref(false);
  91. const showShare = ref(false);
  92. // const isMusicPlaying = ref(false);
  93. // const mode = computed(() => appStore.mode);
  94. const isPanoramaMode = computed(() => appStore.mode === 'panorama');
  95. const description = computed(() => metadata.value.description);
  96. watch(
  97. () => showCopy.value,
  98. (_) => {
  99. appStore.setPlayerOptions({
  100. showMap: !showCopy.value,
  101. showToolbar: !showCopy.value,
  102. });
  103. },
  104. {
  105. deep: true,
  106. },
  107. );
  108. watch(
  109. () => showShare.value,
  110. (_) => {
  111. appStore.setPlayerOptions({
  112. showMap: !showShare.value,
  113. showToolbar: !showShare.value,
  114. });
  115. },
  116. {
  117. deep: true,
  118. },
  119. );
  120. onMounted(() => {
  121. // new ClipboardJS(copy$.value.$el).on('success', function (e) {
  122. // e.clearSelection()
  123. // showCopy.value = false
  124. // Dialog.toast({ content: '场景链接复制成功', type: 'success' })
  125. // })
  126. nextTick(() => {
  127. document.querySelector('.player')?.addEventListener('touchstart', () => {
  128. if (player.value.showMore) {
  129. appStore.setPlayerOptions({
  130. showMore: false,
  131. showMap: true,
  132. showToolbar: true,
  133. });
  134. // store.commit("SetPlayerOptions", {
  135. // showMore: false,
  136. // showMap: true,
  137. // showToolbar: true,
  138. // });
  139. } else if (player.value.showDescription) {
  140. appStore.setPlayerOptions({
  141. showDescription: false,
  142. showMap: true,
  143. showToolbar: true,
  144. });
  145. }
  146. });
  147. (window as any).Back = () => {
  148. onBack();
  149. };
  150. // musicPlayer.on('play', () => (showMusicPlaying.value = true))
  151. // musicPlayer.on('pause', () => (showMusicPlaying.value = false))
  152. });
  153. });
  154. const onBack = () => {
  155. player.value.showVR && appStore.showVR();
  156. };
  157. const onShowMore = () => {
  158. showCopy.value = true;
  159. // let show = !player.value.showMore
  160. // store.commit('SetPlayerOptions', {
  161. // showMore: show,
  162. // showMap: show == false,
  163. // showToolbar: show == false,
  164. // showDescription: false,
  165. // })
  166. };
  167. const onShowDescription = () => {
  168. let show = !player.value.showDescription;
  169. appStore.setPlayerOptions({
  170. showMore: false,
  171. showMap: show == false,
  172. showToolbar: show == false,
  173. showDescription: show,
  174. });
  175. };
  176. // const onMusicClick = () => {
  177. // showMusicPlaying.value ? musicPlayer.pause() : musicPlayer.play();
  178. // };
  179. // const onMenuClick = (name) => {
  180. // appStore.setPlayerOptions({
  181. // showMore: false,
  182. // showDescription: false,
  183. // showMap: true,
  184. // showToolbar: true,
  185. // });
  186. // nextTick(() => {
  187. // if (name == "music") {
  188. // onMusicClick();
  189. // } else if (name == "share") {
  190. // showCopy.value = true;
  191. // } else if (name === "measure") {
  192. // this.$bus.emit("measure/Handle", "start");
  193. // } else if (name == "vr") {
  194. // store.commit("showVR");
  195. // }
  196. // });
  197. // };
  198. // const onShare = (name) => {
  199. // if (name == 'copy') {
  200. // showShare.value = false;
  201. // this.$nextTick(() => {
  202. // showCopy.value = true;
  203. // });
  204. // }
  205. // };
  206. const onChangeMode = () => {
  207. // store.commit("setMode", "panorama");
  208. appStore.setMode('panorama');
  209. };
  210. </script>
  211. <style lang="scss" scoped>
  212. .disable {
  213. opacity: 1;
  214. }
  215. .header {
  216. position: absolute;
  217. top: 0.3rem;
  218. left: 0;
  219. height: 40px;
  220. width: 100%;
  221. z-index: 101;
  222. color: #fff;
  223. display: flex;
  224. align-items: center;
  225. text-shadow: 0px 0px 4px rgba(0, 0, 0, 0.4);
  226. &.app {
  227. top: 1rem;
  228. }
  229. .left {
  230. width: 1rem;
  231. height: 100%;
  232. display: flex;
  233. align-items: center;
  234. justify-content: center;
  235. &.show {
  236. visibility: visible;
  237. pointer-events: auto;
  238. .back {
  239. visibility: visible;
  240. }
  241. }
  242. .back {
  243. width: 0.78rem;
  244. height: 0.78rem;
  245. border-radius: 50%;
  246. background-color: rgba(0, 0, 0, 0.3);
  247. display: flex;
  248. align-items: center;
  249. justify-content: center;
  250. visibility: hidden;
  251. position: relative;
  252. i {
  253. font-size: 0.3rem;
  254. width: auto;
  255. position: static;
  256. }
  257. }
  258. .back-pano {
  259. width: 100%;
  260. height: 100%;
  261. display: flex;
  262. align-items: center;
  263. justify-content: center;
  264. // padding-left: 15px;
  265. position: relative;
  266. i {
  267. font-size: 0.6rem;
  268. position: static;
  269. }
  270. }
  271. }
  272. .right {
  273. position: relative;
  274. width: 1.28rem;
  275. height: 100%;
  276. padding-right: 30px;
  277. display: flex;
  278. align-items: center;
  279. justify-content: flex-end;
  280. z-index: 11;
  281. > i {
  282. font-size: 0.45rem;
  283. color: rgba(255, 255, 255, 0.88);
  284. }
  285. > div {
  286. position: absolute;
  287. display: flex;
  288. flex-direction: column;
  289. right: 10px;
  290. top: 1.3rem;
  291. padding: 4px 0.42105rem;
  292. background-color: rgba(0, 0, 0, 0.5);
  293. border-radius: 5px;
  294. &::after {
  295. content: '';
  296. position: absolute;
  297. top: -5px;
  298. right: 0.3rem;
  299. width: 0;
  300. height: 0;
  301. border-width: 0 5px 5px;
  302. border-style: solid;
  303. border-color: transparent transparent rgba(0, 0, 0, 0.5);
  304. }
  305. &.flex {
  306. li {
  307. span {
  308. flex: 1;
  309. width: auto;
  310. // min-width: 2.8rem;
  311. }
  312. }
  313. }
  314. li {
  315. position: relative;
  316. display: flex;
  317. align-items: center;
  318. justify-content: center;
  319. // margin-top: 0.3rem;
  320. font-size: 0;
  321. // height: .5333rem;
  322. padding: 0.1333rem 0 0.2667rem;
  323. i {
  324. // position: absolute;
  325. // left: 0;
  326. // top: 0;
  327. // font-size: 0.45rem;
  328. font-size: 0.3733rem;
  329. margin-right: 0.4rem;
  330. }
  331. b {
  332. position: absolute;
  333. left: 0.32rem;
  334. top: 0.33rem;
  335. width: 7px;
  336. height: 7px;
  337. border-radius: 50%;
  338. background-color: #00c2c4;
  339. i {
  340. color: #fff;
  341. font-size: 12px;
  342. transform: scale(0.3, 0.3);
  343. top: -4px;
  344. left: -3px;
  345. position: absolute;
  346. }
  347. }
  348. span {
  349. width: 1.89474rem;
  350. white-space: nowrap;
  351. text-align: left;
  352. // padding-bottom: 0.3rem;
  353. // margin-left: 0.75rem;
  354. font-size: 0.3733rem;
  355. // text-indent: 0.2rem;
  356. // padding-right: 0.2rem;
  357. }
  358. }
  359. .home {
  360. border-top: solid 1px rgba(255, 255, 255, 0.4);
  361. a {
  362. width: 1.89474rem;
  363. margin-top: 0.3rem;
  364. margin-bottom: 0.1rem;
  365. margin-left: auto;
  366. margin-right: auto;
  367. display: block;
  368. text-decoration: none;
  369. overflow: hidden;
  370. img {
  371. width: 100%;
  372. outline: none;
  373. border: none;
  374. }
  375. }
  376. }
  377. }
  378. }
  379. .title {
  380. display: flex;
  381. flex: 1;
  382. width: 100%;
  383. height: 100%;
  384. font-size: 14px;
  385. letter-spacing: 1px;
  386. align-items: center;
  387. justify-content: center;
  388. > div {
  389. display: flex;
  390. transition: background 0.3s ease, min-width 0.3s ease, border-radius 0.3s ease;
  391. align-items: center;
  392. justify-content: center;
  393. padding-right: 12px;
  394. padding-left: 12px;
  395. white-space: nowrap;
  396. position: absolute;
  397. height: 100%;
  398. min-width: 100%;
  399. overflow: visible;
  400. pointer-events: none;
  401. background: linear-gradient(
  402. 90deg,
  403. transparent,
  404. rgba(0, 0, 0, 0.2) 29%,
  405. rgba(0, 0, 0, 0.2) 69%,
  406. transparent
  407. );
  408. }
  409. span {
  410. display: inline-block;
  411. position: relative;
  412. white-space: nowrap;
  413. overflow: hidden;
  414. text-overflow: ellipsis;
  415. max-width: 7rem;
  416. display: inline-block;
  417. padding-right: 20px;
  418. i {
  419. position: absolute;
  420. right: 0;
  421. color: #fff;
  422. font-size: 10px;
  423. top: 50%;
  424. -webkit-transform: translateY(-50%);
  425. transform: translateY(-50%);
  426. vertical-align: bottom;
  427. line-height: normal;
  428. }
  429. }
  430. &.up {
  431. i {
  432. transform: translateY(-50%) rotate(180deg);
  433. }
  434. > div {
  435. min-width: 0;
  436. //position: static;
  437. flex-shrink: 0;
  438. background-color: rgba(0, 0, 0, 0.5);
  439. border-radius: 1.15789rem;
  440. }
  441. &.dark {
  442. > div {
  443. background-color: rgba(0, 0, 0, 0.8);
  444. }
  445. }
  446. }
  447. &.empty {
  448. i {
  449. display: none;
  450. }
  451. }
  452. }
  453. .content {
  454. position: absolute;
  455. top: 1.2rem;
  456. left: 0.92105rem;
  457. right: 0.92105rem;
  458. padding: 10px;
  459. background: rgba(0, 0, 0, 0.5);
  460. border-radius: 5px;
  461. font-size: 0.36842rem;
  462. text-align: center;
  463. &.dark {
  464. background: rgba(0, 0, 0, 0.8);
  465. }
  466. > div {
  467. display: inline-block;
  468. text-align: left;
  469. letter-spacing: 1px;
  470. word-break: break-all;
  471. white-space: normal;
  472. line-height: 1.5;
  473. // h4 {
  474. // margin: 0;
  475. // padding: 0;
  476. // margin-bottom: 0.28rem;
  477. // font-size: 0.43rem;
  478. // padding-left: 0.18789rem;
  479. // width: 100%;
  480. // position: relative;
  481. // &::before {
  482. // content: "";
  483. // position: absolute;
  484. // left: 0;
  485. // top: 50%;
  486. // height: 80%;
  487. // transform: translateY(-50%);
  488. // width: 2px;
  489. // background-color: var(--editor-main-color);
  490. // }
  491. // }
  492. :deep(p) {
  493. word-break: break-word;
  494. }
  495. :deep(a) {
  496. color: var(--editor-main-color);
  497. }
  498. }
  499. // &::after {
  500. // content: "";
  501. // position: absolute;
  502. // top: -6px;
  503. // left: 50%;
  504. // margin-left: -3px;
  505. // width: 0;
  506. // height: 0;
  507. // border-width: 0 7px 6px;
  508. // border-style: solid;
  509. // border-color: transparent transparent rgba(0, 0, 0, 0.5);
  510. // }
  511. }
  512. .app-share {
  513. position: fixed;
  514. left: 0;
  515. bottom: 0;
  516. width: 100%;
  517. background-color: #fff;
  518. color: var(--editor-main-color);
  519. text-shadow: none;
  520. border-radius: 0.146667rem 0.146667rem 0px 0px;
  521. i {
  522. // font-size: 2rem;
  523. font-size: 1rem;
  524. margin: 0.666667rem 0 0.106667rem;
  525. display: inline-block;
  526. }
  527. ul {
  528. // display: flex;
  529. // justify-content: space-around;
  530. overflow: hidden;
  531. div {
  532. text-align: center;
  533. // margin-top: -0.3rem;
  534. font-size: 0.34rem;
  535. }
  536. li {
  537. width: 33.3%;
  538. float: left;
  539. // padding-bottom: 0.5rem;
  540. overflow: hidden;
  541. text-align: center;
  542. // i{
  543. // font-size: 2rem;
  544. // }
  545. }
  546. &.flex {
  547. display: flex;
  548. li {
  549. float: none;
  550. }
  551. }
  552. }
  553. > div {
  554. height: 1.293333rem;
  555. font-size: 16px;
  556. text-align: center;
  557. // padding: 0.5rem;
  558. border-top: solid 1px #eeeeee;
  559. margin-top: 0.466667rem;
  560. line-height: 1.293333rem;
  561. }
  562. }
  563. }
  564. .url-share {
  565. position: fixed;
  566. top: 0;
  567. left: 0;
  568. right: 0;
  569. bottom: 0;
  570. z-index: 99999;
  571. background-color: rgba(0, 0, 0, 0.8);
  572. > img {
  573. position: absolute;
  574. width: 61.6%;
  575. top: 12px;
  576. right: 6.4%;
  577. }
  578. > div {
  579. position: absolute;
  580. left: 0.6rem;
  581. right: 0.6rem;
  582. top: 50vh;
  583. transform: translateY(-50%);
  584. border-radius: 4px;
  585. background-color: rgba(0, 0, 0, 0.5);
  586. padding: 0.31579rem;
  587. font-size: 0.36842rem;
  588. .tips {
  589. display: flex;
  590. align-items: center;
  591. justify-content: space-between;
  592. h4 {
  593. margin: 0;
  594. font-size: 0.42105rem;
  595. }
  596. i {
  597. font-size: 0.6rem;
  598. }
  599. }
  600. .url {
  601. display: -webkit-box;
  602. color: #fff;
  603. text-align: center;
  604. padding: 0.26316rem;
  605. width: 100%;
  606. height: 1.8rem;
  607. margin: 0.7rem 0rem;
  608. border-radius: 0.07rem;
  609. line-height: 1.99;
  610. font-size: 0.36842rem;
  611. background-color: rgba(0, 0, 0, 0.35);
  612. overflow: hidden;
  613. text-overflow: ellipsis;
  614. word-break: break-all;
  615. word-wrap: break-word;
  616. -webkit-line-clamp: 2; //在第幾行加省略號
  617. -webkit-box-orient: vertical;
  618. }
  619. .btns {
  620. display: flex;
  621. justify-content: space-between;
  622. button {
  623. font-size: 0.36842rem;
  624. width: 47%;
  625. height: 1.05263rem;
  626. border-radius: 1.05263rem;
  627. &.submit {
  628. background: #00c2c4;
  629. }
  630. }
  631. }
  632. }
  633. }
  634. @media (orientation: landscape) {
  635. .header {
  636. top: 0.2rem;
  637. height: 0.7rem;
  638. &.app {
  639. top: 0.2rem;
  640. }
  641. .left {
  642. .back-pano {
  643. i {
  644. font-size: 0.5rem;
  645. }
  646. }
  647. }
  648. .right {
  649. > i {
  650. font-size: 0.5rem;
  651. }
  652. > div {
  653. right: 10px;
  654. top: 0.75rem;
  655. padding: 4px 0.2rem;
  656. &::after {
  657. right: 0.23rem;
  658. }
  659. li {
  660. margin-top: 0.15rem;
  661. i {
  662. font-size: 0.3rem;
  663. }
  664. b {
  665. left: 0.2rem;
  666. top: 0.15rem;
  667. }
  668. span {
  669. padding-bottom: 0.15rem;
  670. margin-left: 0.5rem;
  671. font-size: 0.25rem;
  672. }
  673. }
  674. .home {
  675. a {
  676. margin-top: 0.15rem;
  677. margin-bottom: 0rem;
  678. width: 1.4rem;
  679. }
  680. }
  681. }
  682. }
  683. .title {
  684. font-size: 0.3rem;
  685. }
  686. .content {
  687. top: 1rem;
  688. left: 2rem;
  689. right: 2rem;
  690. padding: 10px;
  691. > div {
  692. max-height: 3rem;
  693. font-size: 0.25rem;
  694. line-height: 1.5;
  695. }
  696. }
  697. }
  698. }
  699. // ipad 橫屏
  700. @media only screen and (min-device-width: 768px) and (orientation: landscape) {
  701. .header {
  702. height: 0.8rem;
  703. .title {
  704. i {
  705. margin-bottom: 0;
  706. }
  707. }
  708. }
  709. }
  710. // @media only screen and (min-device-width: 768px) and (orientation: portrait) {
  711. // }
  712. </style>
  713. <style lang="scss">
  714. .animated.short {
  715. &.faster {
  716. animation-duration: 0.3s;
  717. }
  718. @keyframes fadeInUp {
  719. 0% {
  720. opacity: 0;
  721. transform: translate3d(0, 1rem, 0);
  722. }
  723. to {
  724. opacity: 1;
  725. transform: translateZ(0);
  726. }
  727. }
  728. @keyframes fadeOutDown {
  729. 0% {
  730. opacity: 1;
  731. }
  732. to {
  733. opacity: 0;
  734. transform: translate3d(0, 1rem, 0);
  735. }
  736. }
  737. }
  738. </style>