HomeView.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. <script setup>
  2. import { ref, computed, nextTick, onMounted, watch } from "vue"
  3. import { useRouter, useRoute } from "vue-router"
  4. import { useStore } from "vuex"
  5. import Startup from "@/views/StartupView.vue"
  6. import useRollFu from "../rollFu.js"
  7. import HotspotDetail3 from "@/views/HotspotDetail3.vue"
  8. import HotspotDetail1 from "@/views/HotspotDetail1.vue"
  9. import PaintingDetail from '@/views/PaintingDetail.vue'
  10. import DetailImg from '@/assets/images/icon_home_detail-min.png'
  11. import DetailImgAc from '@/assets/images/icon_home_detail-min-ac.png'
  12. import AuthorImg from '@/assets/images/icon_home_author-min.png'
  13. import AuthorImgAc from '@/assets/images/icon_home_author-min-ac.png'
  14. import useSizeAdapt from "@/useFunctions/useSizeAdapt"
  15. const store = useStore()
  16. const router = useRouter()
  17. const route = useRoute()
  18. const { handleScrollThrottle } = useRollFu()
  19. const isShowOperationTip = ref(true)
  20. const isShowHotspotDetail1 = ref(false)
  21. const isShowHotspotDetail3 = ref(false)
  22. const curPageIndex = ref(0)
  23. const longDescText = computed(() => {
  24. return curPageIndex.value == 1
  25. ? configText.homepagePaintingDetailDescStem
  26. : curPageIndex.value == 2
  27. ? configText.homepagePaintingDetailDescLeaf
  28. : curPageIndex.value == 3
  29. ? configText.homepagePaintingDetailDescStone
  30. : curPageIndex.value == 4
  31. ? configText.homepagePaintingSummary
  32. : ""
  33. })
  34. const isShowVideoFadeToNextPage = ref(false)
  35. const isShowSkip = ref(false)
  36. const videoFadeToNextPageEl = ref(null)
  37. const paintingState = ref('1')
  38. const isShowPaintingDetial = ref(false)
  39. const longTitleText = computed(() => {
  40. return curPageIndex.value == 1
  41. ? "三竿修竹"
  42. : curPageIndex.value == 2
  43. ? "竹叶"
  44. : curPageIndex.value == 3
  45. ? "卧石、枯树和灌木"
  46. : ""
  47. })
  48. const isShowHotspot = ref(true)
  49. let timeoutIdHotspot = null
  50. watch(curPageIndex, (val) => {
  51. clearTimeout(timeoutIdHotspot)
  52. if (val == 0 || val == 4) {
  53. timeoutIdHotspot = setTimeout(() => {
  54. isShowHotspot.value = true
  55. }, 1500)
  56. }
  57. isShowHotspot.value = false
  58. })
  59. // const isShowHotspot = computed(setTimeout(()=> {
  60. // return curPageIndex.value == 0 || curPageIndex.value == 4
  61. // }, 1500))
  62. // 滑动逻辑
  63. const scrollFu = (event, val) => {
  64. console.log('在滚动', val)
  65. if (val == -1) {
  66. // 上滚
  67. // console.log("上滚")
  68. curPageIndex.value =
  69. curPageIndex.value > 0 ? curPageIndex.value - 1 : curPageIndex.value
  70. } else if (val == 1) {
  71. // 下滚
  72. isShowOperationTip.value = false
  73. if (curPageIndex.value < 4) {
  74. curPageIndex.value = curPageIndex.value + 1
  75. } else if (curPageIndex.value == 4) {
  76. // 播放视频
  77. isShowVideoFadeToNextPage.value = true
  78. nextTick(() => {
  79. videoFadeToNextPageEl.value.play()
  80. })
  81. setTimeout(() => {
  82. isShowSkip.value = true
  83. }, 2000)
  84. }
  85. }
  86. }
  87. const hoverIndex = ref(null)
  88. const {
  89. windowSizeInCssForRef,
  90. windowSizeWhenDesignForRef,
  91. } = useSizeAdapt()
  92. onMounted(() => {
  93. if (route.query.page) {
  94. curPageIndex.value = parseInt(route.query.page)
  95. }
  96. })
  97. </script>
  98. <template>
  99. <div class="home">
  100. <!-- 过渡到更多详情页视频 -->
  101. <video
  102. v-show="isShowVideoFadeToNextPage"
  103. ref="videoFadeToNextPageEl"
  104. muted
  105. class="fade-to-next-page"
  106. src="@/assets/videos/fade-from-home-to-more-content.mp4"
  107. @ended="
  108. router.push({
  109. name: 'MoreContent',
  110. })
  111. "
  112. />
  113. <Transition name="fade-in">
  114. <BtnSkip
  115. v-if="isShowSkip"
  116. @click="
  117. router.push({
  118. name: 'MoreContent',
  119. })
  120. "
  121. />
  122. </Transition>
  123. <!-- 滚动区域 -->
  124. <div
  125. ref="scroller"
  126. class="scroller"
  127. @wheel="($event) => handleScrollThrottle($event, ($event) => scrollFu($event,-1),($event) => scrollFu($event,1))"
  128. >
  129. <div class="scroller-content" />
  130. </div>
  131. <!-- 背景 -->
  132. <div class="bg-mask" />
  133. <!-- 开场动画 -->
  134. <Transition name="fade-out">
  135. <Startup
  136. v-if="!store.state.haveShownStartup"
  137. class="startup"
  138. />
  139. <!-- <Startup
  140. v-if="true"
  141. class="startup"
  142. /> -->
  143. </Transition>
  144. <!-- 首页标题 -->
  145. <div
  146. class="title-wrap"
  147. :style="{
  148. opacity: curPageIndex == 0 ? 1 : 0,
  149. }"
  150. >
  151. <img
  152. class="title"
  153. src="@/assets/images/home-title.png"
  154. alt=""
  155. draggable="false"
  156. >
  157. <div class="sub-text">
  158. <!-- 南京博物院<br> -->
  159. 绢本 墨笔<br>
  160. 元 李衎<br>
  161. </div>
  162. </div>
  163. <!-- 作品、作者简介 -->
  164. <div
  165. ref="longDesc"
  166. class="long-desc"
  167. :class="{ 'long-desc-ac': curPageIndex == 0 || curPageIndex == 4 }"
  168. :style="{ opacity: curPageIndex == 0 || curPageIndex == 4 ? 1 : 0 }"
  169. >
  170. <div
  171. class="page2-box"
  172. @mouseenter="hoverIndex = 1"
  173. @mouseleave="hoverIndex = null"
  174. @click="
  175. // () => {
  176. // router.push('/painting-detail?idx=home');
  177. // }
  178. isShowPaintingDetial =true,
  179. paintingState = '1'
  180. "
  181. >
  182. <img
  183. :src="hoverIndex == 1 ? DetailImgAc : DetailImg"
  184. alt=""
  185. >
  186. <div>作品简介</div>
  187. </div>
  188. <div
  189. class="page2-box"
  190. style="margin-top: 10px"
  191. @mouseenter="hoverIndex = 2"
  192. @mouseleave="hoverIndex = null"
  193. @click="
  194. // () => {
  195. // router.push('/painting-detail?idx=home&state=2');
  196. // }
  197. isShowPaintingDetial =true,
  198. paintingState = '2'
  199. "
  200. >
  201. <img
  202. :src="hoverIndex == 2 ? AuthorImgAc : AuthorImg"
  203. alt=""
  204. >
  205. <div>作者简介</div>
  206. </div>
  207. </div>
  208. <!-- 画作 -->
  209. <div
  210. class="painting-wrap"
  211. :class="{
  212. 'painting-wrap2': curPageIndex == 1 || curPageIndex == 3,
  213. 'painting-wrap3': curPageIndex == 2,
  214. }"
  215. @click="
  216. () => {
  217. isShowPaintingDetial = true
  218. }
  219. "
  220. >
  221. <img
  222. class="painting-border"
  223. src="@/assets/images/painting-border-new.png"
  224. alt=""
  225. draggable="false"
  226. >
  227. <img
  228. class="painting-stem"
  229. src="@/assets/images/home-painting1.jpg"
  230. alt=""
  231. draggable="false"
  232. >
  233. <!-- <img
  234. class="painting-stem"
  235. src="@/assets/images/home-painting2.jpg"
  236. alt=""
  237. draggable="false"
  238. > -->
  239. <img
  240. :style="{ opacity: curPageIndex == 1 ? 1 : 0, zIndex: 3 }"
  241. class="painting-stem"
  242. src="@/assets/images/home-painting-stem.jpg"
  243. alt=""
  244. >
  245. <img
  246. class="painting-stem"
  247. src="@/assets/images/img_zhuye-min2.png"
  248. alt=""
  249. :style="{
  250. opacity: curPageIndex == 2 ? 1 : 0,
  251. zIndex: 2,
  252. }"
  253. draggable="false"
  254. >
  255. <img
  256. class="painting-stem"
  257. src="@/assets/images/img_stone_all-min.png"
  258. :style="{
  259. opacity: curPageIndex == 3 ? 1 : 0,
  260. zIndex: 2,
  261. }"
  262. alt=""
  263. draggable="false"
  264. >
  265. </div>
  266. <!-- 热点层1 -->
  267. <div
  268. v-show="isShowHotspot"
  269. class="hotspot-wrap"
  270. >
  271. <HotspotForHomepage
  272. class="hotspot-1"
  273. @click="isShowHotspotDetail1 = true"
  274. />
  275. <HotspotForHomepage
  276. class="hotspot-3"
  277. @click="isShowHotspotDetail3 = true"
  278. />
  279. </div>
  280. <!-- 轴/卷/册热点详情 -->
  281. <Transition name="fade-in-out">
  282. <HotspotDetail3
  283. v-if="isShowHotspotDetail3"
  284. class="hotspot-detail"
  285. @close="isShowHotspotDetail3 = false"
  286. />
  287. </Transition>
  288. <!-- 材质热点详情 -->
  289. <Transition name="fade-in-out">
  290. <HotspotDetail1
  291. v-if="isShowHotspotDetail1"
  292. class="hotspot-detail"
  293. @close="isShowHotspotDetail1 = false"
  294. />
  295. </Transition>
  296. <!-- 滑动提示 -->
  297. <OperationTip
  298. v-show="curPageIndex == 0"
  299. class="operation-tip"
  300. text="向下滑动"
  301. :is-show="isShowOperationTip"
  302. />
  303. <!-- 画作详情 -->
  304. <PaintingDetail
  305. v-if="isShowPaintingDetial"
  306. class="painting-detail"
  307. :idx="'home'"
  308. :state="paintingState"
  309. @close="isShowPaintingDetial = false"
  310. />
  311. <!-- 文字介绍 -->
  312. <div
  313. class="text-box"
  314. :style="{
  315. opacity:
  316. curPageIndex == 1 ||
  317. curPageIndex == 2 ||
  318. curPageIndex == 3 ||
  319. curPageIndex == 4
  320. ? 1
  321. : 0,
  322. left: curPageIndex == 4 ? '4%':''
  323. }"
  324. >
  325. <div class="text-box-title">
  326. {{ longTitleText }}
  327. </div>
  328. <!-- <div v-if="curPageIndex == 2">
  329. 竹子的画法
  330. </div> -->
  331. <div
  332. class="text-box-desc"
  333. v-html="longDescText"
  334. />
  335. </div>
  336. </div>
  337. </template>
  338. <style lang="less" scoped>
  339. .home {
  340. width: 100%;
  341. height: 100%;
  342. > video.fade-to-next-page {
  343. position: absolute;
  344. left: 0;
  345. top: 0;
  346. width: 100%;
  347. height: 100%;
  348. object-fit: cover;
  349. z-index: 20;
  350. }
  351. > .scroller {
  352. width: 100vw;
  353. max-height: 100vh;
  354. overflow: auto;
  355. background: rgba(255, 255, 0, 0);
  356. position: absolute;
  357. top: 0;
  358. z-index: 10;
  359. opacity: 0.001;
  360. .scroller-content {
  361. width: 100%;
  362. height: 200vh;
  363. }
  364. }
  365. > .bg-mask {
  366. position: absolute;
  367. left: 0;
  368. top: 0;
  369. width: 100%;
  370. height: 100%;
  371. // background: rgba(60, 89, 71, 0.65);
  372. background: url(@/assets/images/bg-mask.png);
  373. background-size: 100% 100%;
  374. }
  375. > .startup {
  376. z-index: 20;
  377. }
  378. > .title-wrap {
  379. position: absolute;
  380. right: 25%;
  381. top: 50%;
  382. transform: translateY(-50%);
  383. width: 100px;
  384. height: 45%;
  385. z-index: 5;
  386. transition: opacity 1.5s ease;
  387. > img.title {
  388. position: absolute;
  389. left: 0;
  390. top: 0;
  391. width: 100%;
  392. height: 100%;
  393. }
  394. > .sub-text {
  395. position: absolute;
  396. left: 110%;
  397. top: 46%;
  398. transform: translateY(-50%);
  399. writing-mode: vertical-lr;
  400. font-family: KaiTi;
  401. font-weight: 400;
  402. font-size: 20px;
  403. color: #ffffff;
  404. line-height: 30px;
  405. white-space: pre;
  406. letter-spacing: 0.2em;
  407. text-align: center;
  408. }
  409. }
  410. > .long-desc {
  411. position: absolute;
  412. bottom: 30px;
  413. right: 30px;
  414. color: white;
  415. overflow: hidden;
  416. font-family: KaiTi;
  417. color: #ffffff;
  418. animation: none;
  419. display: flex;
  420. flex-direction: column;
  421. justify-content: space-between;
  422. z-index: 10;
  423. transition: opacity 1.5s ease;
  424. > .page2-box {
  425. display: flex;
  426. flex-direction: column;
  427. justify-content: center;
  428. align-items: center;
  429. cursor: pointer;
  430. > img {
  431. width: 75%;
  432. margin-bottom: 10px;
  433. }
  434. > div {
  435. font-size: calc(
  436. 20 / v-bind("windowSizeWhenDesignForRef") *
  437. v-bind("windowSizeInCssForRef")
  438. );
  439. font-family: KaiTi;
  440. }
  441. }
  442. }
  443. > .painting-wrap {
  444. position: absolute;
  445. left: 50%;
  446. top: 50%;
  447. width: calc(97vh / 937 * 552);
  448. height: 97vh;
  449. transform: translate(-50%, -50%);
  450. z-index: 1;
  451. transition: top 1.5s ease, left 1.5s ease, width 1.5s ease, height 1.5s ease;
  452. > .painting-border {
  453. width: 100%;
  454. height: 100%;
  455. position: absolute;
  456. }
  457. > .painting-stem {
  458. width: 80%;
  459. height: 74%;
  460. // height: calc(
  461. // 671 / v-bind("windowSizeWhenDesignForRef") *
  462. // v-bind("windowSizeInCssForRef")
  463. // );
  464. position: absolute;
  465. left: 50%;
  466. transform: translate(-50%, 24%);
  467. transition: opacity 1.5s ease;
  468. }
  469. }
  470. > .painting-wrap2 {
  471. left: 63%;
  472. top: 45%;
  473. width: calc(125vh / 937 * 552);
  474. height: calc(125vh);
  475. }
  476. > .painting-wrap3 {
  477. left: 60%;
  478. top: -20%;
  479. width: calc(600vh / 937 * 552);
  480. height: 600vh;
  481. }
  482. > .hotspot-wrap {
  483. position: absolute;
  484. left: 50%;
  485. top: 50%;
  486. width: calc(97vh / 937 * 552);
  487. height: 97vh;
  488. transform: translate(-50%, -50%);
  489. pointer-events: none;
  490. will-change: transform;
  491. backface-visibility: hidden;
  492. z-index: 10;
  493. transition: opacity 0.5s ease;
  494. & > div {
  495. z-index: 100;
  496. transition: all 1.5s ease-in-out;
  497. cursor: pointer;
  498. // transition: all 1.5s ease-in-out;
  499. }
  500. > .hotspot-1 {
  501. position: absolute;
  502. top: 11vh;
  503. right: 0;
  504. pointer-events: initial;
  505. }
  506. // > .hotspot-2 {
  507. // position: absolute;
  508. // left: 60px;
  509. // top: 60px;
  510. // pointer-events: initial;
  511. // }
  512. > .hotspot-3 {
  513. position: absolute;
  514. bottom: 0vh;
  515. right: -1vh;
  516. pointer-events: initial;
  517. }
  518. }
  519. > .hotspot-detail {
  520. z-index: 21;
  521. }
  522. > .operation-tip {
  523. position: absolute;
  524. right: 30px;
  525. transform: translateX(-50%);
  526. top: 50%;
  527. transform: translateY(-50%);
  528. }
  529. >.painting-detail{
  530. width: 100%;
  531. height: 100%;
  532. position: absolute;
  533. top: 0;
  534. left: 0;
  535. z-index: 30;
  536. }
  537. > .text-box {
  538. max-width: 450px;
  539. position: absolute;
  540. top: 50%;
  541. transform: translateY(-50%);
  542. left: 10%;
  543. color: #ffffff;
  544. font-size: 25px;
  545. line-height: 38px;
  546. font-family: "KaiTi";
  547. transition: opacity 1.5s ease;
  548. z-index: 10;
  549. transition: left 1.5s ease;
  550. .text-box-title {
  551. font-size: 42px;
  552. line-height: 48px;
  553. margin-bottom: 30px;
  554. }
  555. .text-box-desc{
  556. text-indent: 2em;
  557. }
  558. }
  559. }
  560. </style>