PoemList.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. <template>
  2. <!-- pc端才使用 v-touch-->
  3. <!--
  4. v-touch:swipe.left="() => onSwipeChange(1)"
  5. v-touch:swipe.right="() => onSwipeChange(-1)"
  6. :swipe-options="{ direction: 'horizontal' }"
  7. -->
  8. <div
  9. class="poem-list-page"
  10. @touchstart="(e) => touchstart(e.touches[0].pageX)"
  11. @touchmove="(e) => touchmove(e.touches[0].pageX)"
  12. @touchend="(e) => touchend((val) => onSwipeChange(val))"
  13. >
  14. <div
  15. class="RWbox"
  16. :style="`width: ${domWidth}px; left:-${
  17. baseRWboxLeft ? 500 : indexAc * pageWidth}px;
  18. `"
  19. >
  20. <div
  21. v-for="(item1, index1) in listRes"
  22. :key="index1"
  23. :class="`ROW ROW${item1.waiClass + 1} ROWW${index1 + 1}`"
  24. :style="`width:${pageWidth}px; opacity:${
  25. index1 === indexAc ? '1' : isOpcMove ? '0' : ''
  26. }`"
  27. >
  28. <img
  29. v-for="(item2, index2) in item1.imgArr"
  30. :key="index2"
  31. :style="`transform: translateX(${isMoveFu(
  32. index1,
  33. item2.moveNum
  34. )}px);`"
  35. :class="item2.classTxt"
  36. :src="require(`@/assets/images/RW/${item2.imgName}.png`)"
  37. alt=""
  38. >
  39. <!-- 诗句内容 -->
  40. <div
  41. class="ROWtxt"
  42. :class="[`typesetting-${getTypesettingIdx(item1['类型'])}`]"
  43. >
  44. <div class="inner-wrap">
  45. <div class="title-wrap">
  46. <h1>《{{ item1["标题"] }}》</h1>
  47. <div class="sub-title">
  48. <span class="author">{{ item1["作者"] }}</span>
  49. <span class="age">{{ item1["朝代"] }}</span>
  50. </div>
  51. </div>
  52. <p>{{ item1["正文"] }}</p>
  53. </div>
  54. </div>
  55. </div>
  56. </div>
  57. <!-- 最底部的文字提示 -->
  58. <div :class="`RWind ${txtTit ? 'RWindShow' : ''}`">
  59. 暂无更多内容
  60. </div>
  61. <!-- 操作提示 -->
  62. <OperationTip
  63. class="operation-tip"
  64. :direction="'h'"
  65. :text="'下一章'"
  66. color="green"
  67. :is-show="isShowOperationTip"
  68. />
  69. <!-- 返场视频 -->
  70. <div :class="`backVideo ${backVideoFlag ? 'backVideoShow' : ''}`">
  71. <video
  72. ref="backVideoRef"
  73. src="@/assets/images/RW/play.mp4"
  74. playsinline
  75. muted
  76. webkit-playsinline="true"
  77. x5-video-player-type="h5"
  78. />
  79. </div>
  80. <!-- 全局遮罩 -->
  81. <div class="shandow-box" />
  82. <!-- 返回按钮 -->
  83. <div class="RWback">
  84. <BtnBack
  85. class="button-back"
  86. @click="btnBackFu"
  87. />
  88. </div>
  89. <!-- 选择 时代 -->
  90. <div
  91. :class="`RWsBtn ${ageFlga ? 'RWsBtnHide' : ''}`"
  92. @click="ageFlga = true"
  93. >
  94. <img
  95. class=""
  96. :src="require(`@/assets/images/icon_menu.png`)"
  97. alt=""
  98. >
  99. </div>
  100. <!-- 选择时代出来的元素 -->
  101. <div :class="`RWage ${ageFlga ? 'RWageShow' : ''}`">
  102. <div
  103. v-for="item in ageList"
  104. :key="item"
  105. :class="`RWageRow ${ageAc === item ? 'RWageRowAc' : ''}`"
  106. @click="cutAgeFu(item)"
  107. >
  108. {{ item }}
  109. </div>
  110. <div
  111. class="RWageImg"
  112. @click="ageFlga = false"
  113. >
  114. <img
  115. class=""
  116. :src="require(`@/assets/images/icon_close.png`)"
  117. alt=""
  118. >
  119. </div>
  120. </div>
  121. </div>
  122. </template>
  123. <script setup>
  124. import { ref, onMounted } from "vue"
  125. import { useRouter } from "vue-router"
  126. import useSizeAdapt from "@/useFunctions/useSizeAdapt"
  127. import { arrList } from "./PoemList.js"
  128. import useMoveFu from "../moveFu"
  129. const { touchstart, touchmove, touchend } = useMoveFu()
  130. /**
  131. * 排版
  132. */
  133. function getTypesettingIdx(poemType) {
  134. switch (poemType) {
  135. case "七绝":
  136. return 1
  137. case "七律":
  138. return 2
  139. case "五绝":
  140. return 3
  141. case "五律":
  142. return 4
  143. default:
  144. return 2
  145. }
  146. }
  147. // 提示语的显示隐藏
  148. const titShow = ref(true)
  149. const router = useRouter()
  150. // 返场视频ref
  151. const backVideoRef = ref("")
  152. const backVideoFlag = ref(false)
  153. // 点击返回
  154. const btnBackFu = () => {
  155. backVideoRef.value.play()
  156. setTimeout(() => {
  157. backVideoFlag.value = true
  158. }, 100)
  159. setTimeout(() => {
  160. router.replace({
  161. name: "MoreContent",
  162. query: {
  163. anchorIdx: 1,
  164. },
  165. })
  166. }, 2200)
  167. }
  168. const { windowSizeInCssForRef, windowSizeWhenDesignForRef } = useSizeAdapt()
  169. const listRes = ref(arrList)
  170. // 元素总宽度
  171. const domWidth = ref(0)
  172. const pageWidth = ref(0)
  173. // 当前选中索引
  174. const indexAc = ref(0)
  175. const baseRWboxLeft = ref(true)
  176. onMounted(() => {
  177. setTimeout(() => {
  178. baseRWboxLeft.value = false
  179. }, 500)
  180. })
  181. // 底部文字提示显示和隐藏
  182. const txtTit = ref(false)
  183. const poemList = configExcel["诗词"]
  184. const isOpcMove = ref(true)
  185. // 时代数组
  186. const ageList = ref([])
  187. // 时代选中
  188. const ageAc = ref(poemList[0]["朝代"])
  189. // 时代显示隐藏切换
  190. const ageFlga = ref(false)
  191. // 切换时代
  192. const cutAgeFu = (val) => {
  193. const index = listRes.value.findIndex((v) => v["朝代"] === val)
  194. if (indexAc.value === index) return
  195. isShowOperationTip.value = false
  196. titShow.value = false
  197. isOpcMove.value = false
  198. setTimeout(() => {
  199. isOpcMove.value = true
  200. }, 500)
  201. indexAc.value = index
  202. ageAc.value = val
  203. }
  204. onMounted(() => {
  205. const tempArr = []
  206. const imgDataLenght = arrList.length
  207. // 整个数组能分为多少段,向上取整
  208. const isArrNum = Math.ceil(poemList.length / imgDataLenght)
  209. for (let i = 0; i < isArrNum; i++) {
  210. tempArr.push(poemList.slice(i * imgDataLenght, (i + 1) * imgDataLenght))
  211. }
  212. const ageListTemp = []
  213. const arrRes = []
  214. tempArr.forEach((v1) => {
  215. v1.forEach((v2, i2) => {
  216. v2.imgArr = arrList[i2]
  217. v2.waiClass = i2
  218. arrRes.push(v2)
  219. if (!ageListTemp.includes(v2["朝代"])) ageListTemp.push(v2["朝代"])
  220. })
  221. })
  222. // console.log("-----", arrRes)
  223. ageList.value = ageListTemp
  224. listRes.value = arrRes
  225. const fullWidth = window.innerWidth >= 500 ? 500 : window.innerWidth
  226. pageWidth.value = fullWidth
  227. // 总盒子的宽度
  228. domWidth.value = fullWidth * poemList.length
  229. })
  230. // 向右是-1
  231. // 向左是 1
  232. const indexFlag = ref(0)
  233. const isShowOperationTip = ref(true)
  234. // 左右滑动
  235. const onSwipeChange = (val) => {
  236. isShowOperationTip.value = false
  237. let numResTemp = indexAc.value + val
  238. let indexFlagTemp = -val
  239. if (val === -1 && indexAc.value === 0) {
  240. // 第一个页面左滑
  241. txtTit.value = true
  242. setTimeout(() => {
  243. txtTit.value = false
  244. }, 1000)
  245. return
  246. }
  247. if (val === 1 && indexAc.value === listRes.value.length - 1) {
  248. // numResTemp = 0
  249. txtTit.value = true
  250. setTimeout(() => {
  251. txtTit.value = false
  252. }, 1000)
  253. return
  254. }
  255. titShow.value = false
  256. indexAc.value = numResTemp
  257. indexFlag.value = indexFlagTemp
  258. // 底部朝代也要变化
  259. ageAc.value = listRes.value[numResTemp]["朝代"]
  260. }
  261. // 是否触发移动的逻辑
  262. const isMoveFu = (index, num) => {
  263. let numRes
  264. if (index === indexAc.value) numRes = 0
  265. else numRes = indexFlag.value * num * 2
  266. return numRes
  267. }
  268. </script>
  269. <style lang="less" scoped>
  270. .poem-list-page {
  271. position: relative;
  272. width: 100%;
  273. height: 100%;
  274. background-color: #f3f4ef;
  275. .RWsBtn {
  276. position: absolute;
  277. z-index: 22;
  278. right: 20px;
  279. bottom: 20px;
  280. width: 30px;
  281. height: 30px;
  282. border-radius: 50%;
  283. // background-color: rgba(0, 0, 0, 0.5);
  284. display: flex;
  285. justify-content: center;
  286. align-items: center;
  287. opacity: 1;
  288. transition: all 0.5s;
  289. & > img {
  290. width: 40px;
  291. }
  292. }
  293. .RWsBtnHide {
  294. opacity: 0;
  295. pointer-events: none;
  296. }
  297. .RWage {
  298. position: absolute;
  299. z-index: 22;
  300. right: -220px;
  301. bottom: 20px;
  302. display: flex;
  303. align-items: center;
  304. justify-content: flex-end;
  305. width: calc(100% - 70px);
  306. height: 30px;
  307. transition: all 0.5s;
  308. opacity: 0;
  309. pointer-events: none;
  310. .RWageRow {
  311. transition: all 0.5s;
  312. width: 30px;
  313. height: 30px;
  314. border-radius: 4px;
  315. background-color: rgba(0, 0, 0, 0.5);
  316. font-family: KingHwa_OldSong;
  317. font-size: 16px;
  318. margin-right: 15px;
  319. text-align: center;
  320. line-height: 30px;
  321. color: #fff;
  322. border: 1px solid transparent;
  323. }
  324. .RWageRowAc {
  325. color: #d6cda1;
  326. border: 1px solid #d6cda1;
  327. font-size: 18px;
  328. }
  329. .RWageImg {
  330. width: 30px;
  331. height: 30px;
  332. border-radius: 50%;
  333. background-color: rgba(0, 0, 0, 0.5);
  334. display: flex;
  335. justify-content: center;
  336. align-items: center;
  337. & > img {
  338. width: 20px;
  339. }
  340. }
  341. }
  342. .RWageShow {
  343. right: 20px;
  344. opacity: 1;
  345. pointer-events: auto;
  346. }
  347. .RWbox {
  348. width: 8000px;
  349. height: 100%;
  350. overflow: hidden;
  351. position: relative;
  352. display: flex;
  353. background-image: url("../assets/images/RW/bg_caizhi.jpg");
  354. background-size: contain;
  355. transition: left 0.8s;
  356. .ROW {
  357. position: relative;
  358. transition: opacity 1.2s;
  359. & > img {
  360. position: absolute;
  361. bottom: 0;
  362. height: 100%;
  363. transition: transform 1s;
  364. }
  365. }
  366. .ROW {
  367. .ROW1_1 {
  368. left: 0;
  369. }
  370. .ROW1_2 {
  371. z-index: 2;
  372. right: 0;
  373. }
  374. .ROW1_3 {
  375. right: 5%;
  376. }
  377. .ROW2_1 {
  378. z-index: 2;
  379. left: -38%;
  380. }
  381. .ROW2_2 {
  382. right: 5%;
  383. }
  384. .ROW2_3 {
  385. z-index: 3;
  386. right: -20%;
  387. }
  388. .ROW3_1 {
  389. left: -36%;
  390. }
  391. .ROW3_2 {
  392. height: 15%;
  393. left: 10%;
  394. }
  395. .ROW3_3 {
  396. z-index: 2;
  397. height: 15%;
  398. right: 10%;
  399. }
  400. .ROW3_4 {
  401. right: 0%;
  402. }
  403. .ROW3_5 {
  404. right: -5%;
  405. }
  406. .ROW4_1 {
  407. left: -35%;
  408. }
  409. .ROW4_2 {
  410. left: -40%;
  411. height: 15%;
  412. }
  413. .ROW4_3 {
  414. left: 10%;
  415. height: 20%;
  416. }
  417. .ROW4_4 {
  418. right: 6%;
  419. height: 15%;
  420. }
  421. .ROW4_5 {
  422. right: -17%;
  423. }
  424. .ROW5_1 {
  425. left: -45%;
  426. }
  427. .ROW5_2 {
  428. z-index: 2;
  429. left: -17%;
  430. }
  431. .ROW5_3 {
  432. z-index: 3;
  433. left: 5%;
  434. height: 15%;
  435. }
  436. .ROW5_4 {
  437. z-index: 3;
  438. left: 30%;
  439. height: 15%;
  440. }
  441. .ROW5_5 {
  442. right: -6%;
  443. }
  444. .ROW6_1 {
  445. z-index: 3;
  446. left: 2%;
  447. height: 15%;
  448. }
  449. .ROW6_2 {
  450. left: -10%;
  451. }
  452. .ROW6_3 {
  453. z-index: 2;
  454. left: -13%;
  455. }
  456. .ROW6_4 {
  457. right: -10%;
  458. }
  459. .ROW6_5 {
  460. right: -10%;
  461. }
  462. }
  463. .ROWtxt {
  464. display: flex;
  465. justify-content: center;
  466. align-items: center;
  467. width: 100%;
  468. height: 100%;
  469. writing-mode: vertical-rl;
  470. position: relative;
  471. z-index: 10;
  472. .inner-wrap {
  473. > .title-wrap {
  474. position: relative;
  475. width: fit-content;
  476. height: fit-content;
  477. > h1 {
  478. font-family: KingHwa_OldSong;
  479. font-weight: 400;
  480. font-size: calc(
  481. 36 / v-bind("windowSizeWhenDesignForRef") *
  482. v-bind("windowSizeInCssForRef")
  483. );
  484. color: black;
  485. line-height: calc(
  486. 36 / v-bind("windowSizeWhenDesignForRef") *
  487. v-bind("windowSizeInCssForRef")
  488. );
  489. white-space: pre;
  490. letter-spacing: 0.1em;
  491. }
  492. > .sub-title {
  493. position: absolute;
  494. left: 0;
  495. top: 50%;
  496. transform: translate(-140%, -50%);
  497. display: flex;
  498. align-items: center;
  499. > .author {
  500. white-space: pre;
  501. font-family: KaiTi;
  502. font-weight: 400;
  503. font-size: 20px;
  504. color: #b9aa70;
  505. letter-spacing: 0em;
  506. margin-inline-end: calc(
  507. 6 / v-bind("windowSizeWhenDesignForRef") *
  508. v-bind("windowSizeInCssForRef")
  509. );
  510. }
  511. > .age {
  512. display: inline-block;
  513. width: calc(
  514. 21 / v-bind("windowSizeWhenDesignForRef") *
  515. v-bind("windowSizeInCssForRef")
  516. );
  517. height: calc(
  518. 21 / v-bind("windowSizeWhenDesignForRef") *
  519. v-bind("windowSizeInCssForRef")
  520. );
  521. background-color: #b6a261;
  522. border-radius: 50%;
  523. display: flex;
  524. justify-content: center;
  525. align-items: center;
  526. font-family: KaiTi;
  527. font-weight: 400;
  528. font-size: calc(
  529. 16 / v-bind("windowSizeWhenDesignForRef") *
  530. v-bind("windowSizeInCssForRef")
  531. );
  532. color: #ffffff;
  533. }
  534. }
  535. }
  536. > p {
  537. margin-right: calc(
  538. 40 / v-bind("windowSizeWhenDesignForRef") *
  539. v-bind("windowSizeInCssForRef")
  540. );
  541. font-family: KaiTi;
  542. font-weight: 400;
  543. font-size: calc(
  544. 20 / v-bind("windowSizeWhenDesignForRef") *
  545. v-bind("windowSizeInCssForRef")
  546. );
  547. color: black;
  548. line-height: 1.6em;
  549. white-space: pre;
  550. letter-spacing: 0.2em;
  551. }
  552. }
  553. }
  554. .ROWtxt.typesetting-1 {
  555. > .inner-wrap {
  556. transform: translate(10%, -20%);
  557. > p {
  558. margin-top: calc(
  559. 232 / v-bind("windowSizeWhenDesignForRef") *
  560. v-bind("windowSizeInCssForRef")
  561. );
  562. }
  563. }
  564. }
  565. .ROWtxt.typesetting-2 {
  566. > .inner-wrap {
  567. transform: translate(10%, -4%);
  568. > p {
  569. margin-top: calc(
  570. 102 / v-bind("windowSizeWhenDesignForRef") *
  571. v-bind("windowSizeInCssForRef")
  572. );
  573. }
  574. }
  575. }
  576. .ROWtxt.typesetting-3 {
  577. > .inner-wrap {
  578. transform: translate(0, -9%);
  579. > p {
  580. margin-top: calc(
  581. 135 / v-bind("windowSizeWhenDesignForRef") *
  582. v-bind("windowSizeInCssForRef")
  583. );
  584. }
  585. }
  586. }
  587. .ROWtxt.typesetting-4 {
  588. > .inner-wrap {
  589. transform: translate(10%, -10%);
  590. > p {
  591. margin-top: calc(
  592. 200 / v-bind("windowSizeWhenDesignForRef") *
  593. v-bind("windowSizeInCssForRef")
  594. );
  595. }
  596. }
  597. }
  598. }
  599. .ROW1 {
  600. .ROWtxt {
  601. padding-top: 15%;
  602. padding-right: 40%;
  603. }
  604. }
  605. .ROW2 {
  606. .ROWtxt {
  607. padding-right: 24%;
  608. }
  609. }
  610. .ROW3 {
  611. .ROWtxt {
  612. padding-right: 30%;
  613. }
  614. }
  615. .ROWW19 {
  616. .ROWtxt {
  617. padding-top: 87%;
  618. }
  619. }
  620. // 底部文字提示
  621. .RWind {
  622. position: absolute;
  623. bottom: 15%;
  624. left: 50%;
  625. transform: translateX(-50%);
  626. z-index: 30;
  627. font-size: 14px;
  628. color: #b9aa70;
  629. letter-spacing: 4px;
  630. opacity: 0;
  631. transition: opacity 0.5s;
  632. pointer-events: none;
  633. font-family: KingHwa_OldSong;
  634. }
  635. .RWindShow {
  636. opacity: 1;
  637. }
  638. // 操作提示
  639. .operation-tip {
  640. position: absolute;
  641. z-index: 30;
  642. left: 50%;
  643. bottom: 7%;
  644. transform: translateX(-50%);
  645. color: #7f9470;
  646. font-size: 12px;
  647. letter-spacing: 3px;
  648. pointer-events: none;
  649. display: flex;
  650. align-items: center;
  651. opacity: 1;
  652. transition: opacity 1s;
  653. img {
  654. width: 30px;
  655. }
  656. }
  657. .operation-tipHide {
  658. opacity: 0;
  659. }
  660. // 返场视频
  661. .backVideo {
  662. position: absolute;
  663. top: 0;
  664. left: 0;
  665. width: 100%;
  666. height: 100%;
  667. z-index: 30;
  668. opacity: 0;
  669. pointer-events: none;
  670. transition: opacity 2s;
  671. & > video {
  672. width: 100%;
  673. }
  674. }
  675. .backVideoShow {
  676. opacity: 1;
  677. pointer-events: auto;
  678. }
  679. // 返回按钮
  680. .RWback {
  681. position: absolute;
  682. z-index: 22;
  683. left: 20px;
  684. bottom: 20px;
  685. width: 30px;
  686. height: 30px;
  687. border-radius: 50%;
  688. // background-color: rgba(0, 0, 0, 0.5);
  689. display: flex;
  690. justify-content: center;
  691. align-items: center;
  692. }
  693. .btn-back {
  694. position: absolute;
  695. top: 50%;
  696. left: 50%;
  697. transform: translate(-50%, -50%);
  698. max-width: 100%;
  699. max-height: 100%;
  700. }
  701. .shandow-box{
  702. width: 100%;
  703. height:130px;
  704. left:0;
  705. background: linear-gradient(0deg, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 100%);
  706. position:absolute;
  707. bottom: 0;
  708. z-index: 2;
  709. }
  710. }
  711. </style>