HomeMobile.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. <template>
  2. <div class="hotspot-home">
  3. <audio
  4. ref="bg-audio"
  5. class="bg-audio"
  6. :src="bgAudioUrl"
  7. loop
  8. autoplay
  9. />
  10. <button
  11. class="close"
  12. @click="onClickClose"
  13. >
  14. <img
  15. src="@/assets/images/close.png"
  16. alt="关闭"
  17. draggable="false"
  18. >
  19. </button>
  20. <div class="title-wrapper">
  21. <h1
  22. :title="hotspotTextInfo.title"
  23. v-html="hotspotTextInfo.title"
  24. />
  25. <img
  26. src="@/assets/images/title-bottom-line.png"
  27. alt=""
  28. class="bottom-line"
  29. >
  30. </div>
  31. <div
  32. v-if="isShowVideos"
  33. v-show="!isShowShare"
  34. class="swiper-wrapper-mine video-wrap"
  35. >
  36. <div
  37. class="swiper-root"
  38. >
  39. <div
  40. class="swiper-wrapper"
  41. >
  42. <div
  43. v-for="(item, index) in hotspotData.video"
  44. :key="index"
  45. class="swiper-slide"
  46. >
  47. <video
  48. ref="video"
  49. :src="item.url"
  50. controls
  51. controlslist="nodownload"
  52. disablePictureInPicture
  53. />
  54. </div>
  55. </div>
  56. <div class="swiper-pagination" />
  57. <div class="swiper-button-prev" />
  58. <div class="swiper-button-next" />
  59. </div>
  60. </div>
  61. <div
  62. v-if="isShowModels"
  63. class="swiper-wrapper-mine model-wrap"
  64. >
  65. <div
  66. class="swiper-root"
  67. >
  68. <div
  69. class="swiper-wrapper"
  70. >
  71. <iframe
  72. v-for="(item, index) in hotspotData.model"
  73. :key="index"
  74. :src="item"
  75. frameborder="0"
  76. class="swiper-slide"
  77. />
  78. </div>
  79. <div class="swiper-pagination" />
  80. </div>
  81. </div>
  82. <div
  83. v-if="isShowAudios"
  84. v-show="!isShowShare"
  85. class="swiper-wrapper-mine audio-wrap"
  86. >
  87. <div
  88. class="swiper-root"
  89. >
  90. <div
  91. class="swiper-wrapper"
  92. >
  93. <div
  94. v-for="(item, index) in hotspotData.audio"
  95. :key="index"
  96. class="swiper-slide"
  97. >
  98. <audio
  99. ref="audio"
  100. :src="item.url"
  101. controls
  102. controlslist="nodownload"
  103. disablePictureInPicture
  104. />
  105. </div>
  106. </div>
  107. <div class="swiper-pagination" />
  108. </div>
  109. </div>
  110. <div
  111. v-if="isShowImages"
  112. v-show="!isShowShare"
  113. class="swiper-wrapper-mine image-wrap"
  114. >
  115. <div
  116. class="swiper-root"
  117. >
  118. <div
  119. v-viewer="{
  120. button: true,
  121. navbar: false,
  122. title: false,
  123. toolbar: false,
  124. tooltip: false,
  125. movable: true,
  126. zoomable: true,
  127. rotatable: true,
  128. scalable: true,
  129. transition: false,
  130. fullscreen: false,
  131. keyboard: true,
  132. loop: false,
  133. }"
  134. class="swiper-wrapper"
  135. >
  136. <img
  137. v-for="(item, index) in hotspotData.images"
  138. :key="index"
  139. v-lazy="item"
  140. class="swiper-slide"
  141. alt=""
  142. draggable="false"
  143. >
  144. </div>
  145. <div class="swiper-pagination">
  146. <!-- <span
  147. class="cur"
  148. >
  149. {{ currentSlideIdx + 1 }}
  150. </span>
  151. /
  152. <span>
  153. {{ hotspotData.Images ? hotspotData.images.length : '' }}
  154. </span> -->
  155. </div>
  156. <div class="swiper-button-prev" />
  157. <div class="swiper-button-next" />
  158. </div>
  159. </div>
  160. <menu>
  161. <button
  162. v-if="bgAudioUrl"
  163. @click="isBgAudioMuted = !isBgAudioMuted"
  164. >
  165. <img
  166. v-show="isBgAudioMuted"
  167. class="bg-audio-control"
  168. src="@/assets/images/bg-audio-mobile.png"
  169. alt=""
  170. draggable="false"
  171. >
  172. <img
  173. v-show="!isBgAudioMuted"
  174. class="bg-audio-control"
  175. src="@/assets/images/bg-audio-mobile-muted.png"
  176. alt=""
  177. draggable="false"
  178. >
  179. </button>
  180. <!-- <button @click="onClickLike">
  181. <img
  182. class="like"
  183. src="@/assets/images/like-mobile.png"
  184. alt=""
  185. draggable="false"
  186. >
  187. <transition name="bubble">
  188. <div
  189. v-if="isShowPlusOne"
  190. class="plus-one"
  191. >
  192. +1
  193. </div>
  194. </transition>
  195. </button> -->
  196. <!-- <button @click="onClickShare">
  197. <img
  198. class="share"
  199. src="@/assets/images/share-mobile.png"
  200. alt=""
  201. draggable="false"
  202. >
  203. </button> -->
  204. </menu>
  205. <div class="desc-wrap">
  206. <div
  207. class="place-holder"
  208. @mousedown.prevent
  209. @touchstart.prevent
  210. />
  211. <div class="desc-bg-wrap">
  212. <div class="top-bar" />
  213. <div
  214. class="textInfo"
  215. >
  216. <ul>
  217. <li>
  218. <span class="key">时代:</span>
  219. <span class="value">{{ hotspotTextInfo.age }}</span>
  220. </li>
  221. <li>
  222. <span class="key">出土地:</span>
  223. <span class="value">{{ hotspotTextInfo.position }}</span>
  224. </li>
  225. <li>
  226. <span class="key">尺寸:</span>
  227. <span class="value">{{ hotspotTextInfo.size }}</span>
  228. </li>
  229. <li>
  230. <span class="key">介绍:</span>
  231. <span
  232. class="value"
  233. v-html="hotspotTextInfo.desc"
  234. />
  235. </li>
  236. </ul>
  237. </div>
  238. </div>
  239. </div>
  240. <div
  241. v-if="isShowShare"
  242. class="share-wrap"
  243. >
  244. <img
  245. v-click-outside.click="closeCode2d"
  246. src="@/assets/images/code2d.png"
  247. alt=""
  248. class="code"
  249. draggable="false"
  250. >
  251. </div>
  252. </div>
  253. </template>
  254. <script>
  255. import Swiper from 'swiper/swiper-bundle.esm.js'
  256. import 'swiper/swiper-bundle.css'
  257. import bgImg from "@/assets/images/bg.png"
  258. import { deepProcess } from "@/utils/other.js"
  259. // import browser from "@/utils/browser";
  260. import hotspotData from "@/assets/data/hotspotData.js"
  261. export default {
  262. data() {
  263. return {
  264. hotspotData: {}, // 热点数据
  265. bgAudioUrl: "", //背景音频url
  266. isBgAudioMuted: false,
  267. isShowImages: false,
  268. isShowVideos: false,
  269. isShowModels: false,
  270. isShowAudios: false,
  271. currentSlideIdx: 0,
  272. bgImg,
  273. isShowPlusOne: false,
  274. isShowShare: false,
  275. }
  276. },
  277. computed: {
  278. hotspotTextInfo() {
  279. const ret = hotspotData.find((item) => {
  280. return item.id === this.$route.query.m
  281. })
  282. return ret
  283. },
  284. },
  285. watch: {
  286. isBgAudioMuted: {
  287. handler(vNew) {
  288. if (vNew) {
  289. this.$refs['bg-audio'].pause() // or toggle静音?
  290. } else {
  291. this.$refs['bg-audio'].play() // or toggle静音?
  292. }
  293. }
  294. }
  295. },
  296. async mounted() {
  297. await this.getData()
  298. this.$nextTick(() => {
  299. const that = this
  300. new Swiper('.swiper-root', {
  301. pagination: {
  302. el: '.swiper-pagination',
  303. },
  304. navigation: {
  305. nextEl: '.swiper-button-next',
  306. prevEl: '.swiper-button-prev',
  307. },
  308. on: {
  309. // 自动播放
  310. afterInit: function (e) {
  311. if (that.isShowVideos) {
  312. that.$nextTick(() => {
  313. that.$refs.video[0].play()
  314. })
  315. }
  316. if (that.isShowAudios) {
  317. that.$nextTick(() => {
  318. that.$refs.audio[0].play()
  319. })
  320. }
  321. },
  322. slideChange: function(e) {
  323. that.currentSlideIdx = e.activeIndex
  324. // 自动播放
  325. if (that.isShowVideos) {
  326. for (let index = 0; index < that.$refs.video.length; index++) {
  327. if (index !== that.currentSlideIdx) {
  328. that.$refs.video[index].pause()
  329. } else {
  330. that.$refs.video[index].play()
  331. }
  332. }
  333. }
  334. if (that.isShowAudios) {
  335. for (let index = 0; index < that.$refs.audio.length; index++) {
  336. if (index !== that.currentSlideIdx) {
  337. that.$refs.audio[index].pause()
  338. } else {
  339. that.$refs.audio[index].play()
  340. }
  341. }
  342. }
  343. }
  344. }
  345. })
  346. })
  347. },
  348. methods: {
  349. changeSubStr(str) {
  350. return str.replace('https://super.4dage.com/', process.env.VUE_APP_G_PREFIX)
  351. },
  352. async getData() {
  353. let url = `${process.env.VUE_APP_G_PREFIX}/data/${this.$route.query.id}/hot/js/data.js?time=${Math.random()}`
  354. let result = (await this.$http.get(url)).data
  355. deepProcess(result, this.changeSubStr)
  356. this.hotspotData = result[this.$route.query.m]
  357. if (!this.hotspotData) {
  358. return alert("热点解析错误")
  359. }
  360. console.log('热点数据:', this.hotspotData)
  361. // this.bgAudioUrl = this.hotspotData.backgroundMusic
  362. if (this.hotspotData.images && this.hotspotData.images.length) {
  363. this.isShowImages = true
  364. } else if (this.hotspotData.video && this.hotspotData.video.length) {
  365. this.isShowVideos = true
  366. } else if (this.hotspotData.model && this.hotspotData.model.length) {
  367. this.isShowModels = true
  368. } else if (this.hotspotData.backgroundMusic) {
  369. this.isShowAudios = true
  370. this.hotspotData.audio = [{ url: this.hotspotData.backgroundMusic }]
  371. }
  372. },
  373. onClickClose() {
  374. window.parent.document.getElementById('closepop').click()
  375. },
  376. // onClickLike() {
  377. // const res = globalApi.like()
  378. // if (res && res.then) {
  379. // res.then(() => {
  380. // this.isShowPlusOne = true
  381. // setTimeout(() => {
  382. // this.isShowPlusOne = false
  383. // }, 1000)
  384. // })
  385. // }
  386. // },
  387. onClickShare() {
  388. setTimeout(() => {
  389. this.isShowShare = true
  390. }, 200)
  391. },
  392. closeCode2d() {
  393. if (this.isShowShare) {
  394. this.isShowShare = false
  395. }
  396. }
  397. }
  398. }
  399. </script>
  400. <style lang="less" scoped>
  401. .hotspot-home {
  402. position: absolute;
  403. left: 0;
  404. top: 0;
  405. width: 100%;
  406. height: 100%;
  407. color: #F1F3F4;
  408. z-index: 0;
  409. > .bg-audio {
  410. display: none;
  411. }
  412. > button.close {
  413. position: absolute;
  414. top: 20px;
  415. right: 30px;
  416. width: 33.5px;
  417. height: 33.5px;
  418. z-index: 1;
  419. > img {
  420. width: 100%;
  421. height: 100%;
  422. }
  423. }
  424. > .title-wrapper {
  425. position: absolute;
  426. top: 62px;
  427. left: 50%;
  428. transform: translateX(-50%);
  429. width: 90%;
  430. z-index: 1;
  431. > h1 {
  432. width: 100%;
  433. font-size: 27.5px;
  434. line-height: 1.2em;
  435. font-size: 27.5px;
  436. font-family: DFLiShuW7;
  437. letter-spacing: 2px;
  438. text-align: center;
  439. display: -webkit-box;
  440. -webkit-box-orient: vertical;
  441. -webkit-line-clamp: 2;
  442. overflow: hidden;
  443. }
  444. > .bottom-line {
  445. position: absolute;
  446. top: 100%;
  447. left: calc(50% + 10px);
  448. transform: translateX(-50%);
  449. width: 174px;
  450. height: 9.5px;
  451. }
  452. }
  453. .swiper-wrapper-mine {
  454. position: absolute;
  455. top: 150px;
  456. left: 0px;
  457. width: 100%;
  458. height: 250px;
  459. z-index: 1;
  460. .swiper-root {
  461. overflow: hidden;
  462. height: 100%;
  463. width: 100%;
  464. .swiper-wrapper {
  465. }
  466. .swiper-pagination {
  467. position: absolute;
  468. top: 100%;
  469. left: 50%;
  470. transform: translateX(-50%);
  471. font-size: 1.33rem;
  472. font-family: Inter-Regular, Inter;
  473. .cur {
  474. }
  475. }
  476. .swiper-button-prev {
  477. left: 10px;
  478. width: 20px;
  479. background-image: url(../assets/images/arrow-left.png);
  480. background-size: contain;
  481. background-repeat: no-repeat;
  482. background-position: center;
  483. &::after {
  484. content: '';
  485. }
  486. }
  487. .swiper-button-next {
  488. right: 10px;
  489. width: 20px;
  490. background-image: url(../assets/images/arrow-right.png);
  491. background-size: contain;
  492. background-repeat: no-repeat;
  493. background-position: center;
  494. &::after {
  495. content: '';
  496. }
  497. }
  498. }
  499. }
  500. .swiper-wrapper-mine.video-wrap {
  501. .swiper-root {
  502. .swiper-wrapper {
  503. .swiper-slide {
  504. > video {
  505. width: 100%;
  506. height: 100%;
  507. background: #000;
  508. }
  509. }
  510. }
  511. }
  512. }
  513. .swiper-wrapper-mine.model-wrap {
  514. .swiper-root {
  515. .swiper-wrapper {
  516. }
  517. }
  518. }
  519. .swiper-wrapper-mine.audio-wrap {
  520. .swiper-root {
  521. .swiper-wrapper {
  522. .swiper-slide {
  523. > audio {
  524. position: absolute;
  525. top: 50%;
  526. left: 50%;
  527. width: 80%;
  528. transform: translate(-50%, -50%);
  529. }
  530. }
  531. }
  532. }
  533. }
  534. .swiper-wrapper-mine.image-wrap {
  535. .swiper-root {
  536. .swiper-wrapper {
  537. > img {
  538. width: 100%;
  539. height: 100%;
  540. object-fit: contain;
  541. }
  542. }
  543. }
  544. }
  545. > menu {
  546. position: absolute;
  547. top: 415px;
  548. left: 50%;
  549. transform: translateX(-50%);
  550. z-index: 1;
  551. > button {
  552. display: inline-block;
  553. width: 24px;
  554. height: 24px;
  555. margin-right: 38.5px;
  556. position: relative;
  557. &:last-of-type{
  558. margin-right: initial;
  559. }
  560. img {
  561. width: 100%;
  562. height: 100%;
  563. }
  564. // .plus-one {
  565. // position: absolute;
  566. // top: 0;
  567. // right: 0;
  568. // transform: translate(50%, -50%);
  569. // }
  570. }
  571. }
  572. > .desc-wrap {
  573. position: absolute;
  574. top: 0;
  575. left: 0;
  576. right: 0;
  577. bottom: 0;
  578. overflow: auto;
  579. > .place-holder {
  580. width: 100%;
  581. height: 450px;
  582. }
  583. > .desc-bg-wrap {
  584. z-index: 2;
  585. position: absolute;
  586. top: 450px;
  587. left: 50%;
  588. transform: translateX(-50%);
  589. width: calc(100vw - 11px * 2);
  590. height: calc((100vw - 11px * 2) * 1.7);
  591. background-image: url(@/assets/images/bg-mobile.png);
  592. background-size: contain;
  593. background-repeat: no-repeat;
  594. background-position: center center;
  595. > .top-bar {
  596. position: absolute;
  597. top: 20px;
  598. left: 50%;
  599. transform: translateX(-50%);
  600. width: 127px;
  601. height: 4px;
  602. background: #F4D49F;
  603. border-radius: 2px;
  604. }
  605. > .textInfo {
  606. position: absolute;
  607. top: 77px;
  608. bottom: 40px;
  609. left: 26px;
  610. right: 26px;
  611. font-size: 16px;
  612. line-height: 26px;
  613. font-family: Adobe Heiti Std;
  614. overflow: auto;
  615. padding-right: 10px;
  616. &::-webkit-scrollbar { width: 5px; height: 5px; }
  617. > ul {
  618. > li {
  619. display: block;
  620. margin-bottom: 0.5em;
  621. margin-left: 31px;
  622. position: relative;
  623. white-space: pre-wrap;
  624. &::before {
  625. position: absolute;
  626. left: -24px;
  627. top: 6px;
  628. content: '';
  629. background-color: #F1F3F4;
  630. display: inline-block;
  631. width: 12px;
  632. height: 12px;
  633. border-radius: 6px;
  634. }
  635. }
  636. }
  637. }
  638. }
  639. }
  640. .share-wrap {
  641. position: absolute;
  642. top: 0;
  643. left: 0;
  644. width: 100%;
  645. height: 100%;
  646. z-index: 1;
  647. > img.code {
  648. position: absolute;
  649. top: 190px;
  650. left: 50%;
  651. transform: translateX(-50%);
  652. width: 170px;
  653. height: 170px;
  654. }
  655. }
  656. }
  657. /deep/.swiper-pagination-bullet-active {
  658. background: #a10e0c;
  659. }
  660. // .bubble-enter {
  661. // opacity: 0;
  662. // top: 1rem !important;
  663. // }
  664. // .bubble-enter-to {
  665. // opacity: 1;
  666. // top: 0 !important;
  667. // }
  668. // .bubble-enter-active {
  669. // transition: all 0.5s;
  670. // }
  671. // .bubble-leave {
  672. // opacity: 1;
  673. // top: 0 !important;
  674. // }
  675. // .bubble-leave-to {
  676. // opacity: 0;
  677. // top: -1rem !important;
  678. // }
  679. // .bubble-leave-active {
  680. // transition: all 0.5s;
  681. // }
  682. ::-webkit-scrollbar { width: 0; height: 0; } /*宽度是对垂直滚动条而言,高度是对水平滚动条而言*/
  683. </style>