|
@@ -0,0 +1,524 @@
|
|
|
+<template>
|
|
|
+ <div class="poem-list">
|
|
|
+ <div
|
|
|
+ ref="scrollTarget"
|
|
|
+ class="scroll-target"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class="layer-4"
|
|
|
+ :style="{
|
|
|
+ left: layer4Left + 'px',
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="bg"
|
|
|
+ src="@/assets/images/poem-list/bg.jpg"
|
|
|
+ alt=""
|
|
|
+ draggable="false"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="bg"
|
|
|
+ src="@/assets/images/poem-list/bg.jpg"
|
|
|
+ alt=""
|
|
|
+ draggable="false"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="bg"
|
|
|
+ src="@/assets/images/poem-list/bg.jpg"
|
|
|
+ alt=""
|
|
|
+ draggable="false"
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ class="layer-3"
|
|
|
+ :style="{
|
|
|
+ left: layer3Left + 'px',
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="bamboo"
|
|
|
+ src="@/assets/images/poem-list/3-min.png"
|
|
|
+ alt=""
|
|
|
+ draggable="false"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="bamboo"
|
|
|
+ src="@/assets/images/poem-list/3-min.png"
|
|
|
+ alt=""
|
|
|
+ draggable="false"
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ class="layer-2"
|
|
|
+ :style="{
|
|
|
+ left: layer2Left + 'px',
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="bamboo"
|
|
|
+ src="@/assets/images/poem-list/2-min.png"
|
|
|
+ alt=""
|
|
|
+ draggable="false"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="bamboo"
|
|
|
+ src="@/assets/images/poem-list/2-min.png"
|
|
|
+ alt=""
|
|
|
+ draggable="false"
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ class="layer-1"
|
|
|
+ :style="{
|
|
|
+ left: layer1Left + 'px',
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="bamboo"
|
|
|
+ src="@/assets/images/poem-list/1-min.png"
|
|
|
+ alt=""
|
|
|
+ draggable="false"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="bamboo"
|
|
|
+ src="@/assets/images/poem-list/1-min.png"
|
|
|
+ alt=""
|
|
|
+ draggable="false"
|
|
|
+ >
|
|
|
+
|
|
|
+ <!-- 诗句内容 -->
|
|
|
+ <div
|
|
|
+ v-for="(item, index) in poemList"
|
|
|
+ :key="index"
|
|
|
+ class="poem"
|
|
|
+ >
|
|
|
+ <div class="title-wrap">
|
|
|
+ <h1>《{{ item["标题"] }}》</h1>
|
|
|
+ <div class="sub-title">
|
|
|
+ <span class="author">{{ item["作者"] }}</span>
|
|
|
+ <span class="age">{{ item["朝代"] }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <p>{{ item["正文"] }}</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="shadow-bottom">
|
|
|
+ <menu class="age-list">
|
|
|
+ <button
|
|
|
+ v-for="(item, idx) in ageList"
|
|
|
+ :key="item.id"
|
|
|
+ class="age"
|
|
|
+ :class="{
|
|
|
+ active: activeAgeIdx === idx,
|
|
|
+ }"
|
|
|
+ @click="onClickAge(item)"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="img-normal"
|
|
|
+ :src="require(`@/assets/images/poem-list/button-${item.id}.png`)"
|
|
|
+ alt=""
|
|
|
+ draggable="false"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="img-active"
|
|
|
+ :src="require(`@/assets/images/poem-list/button-${item.id}-active.png`)"
|
|
|
+ alt=""
|
|
|
+ draggable="false"
|
|
|
+ >
|
|
|
+ </button>
|
|
|
+ </menu>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- todo -->
|
|
|
+ <BtnBack @click="router.replace('/?back=1')" />
|
|
|
+
|
|
|
+ <OperationTip
|
|
|
+ class="operation-tip"
|
|
|
+ :text="'左右滑动'"
|
|
|
+ :color="'green'"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, computed, watch, onBeforeMount, nextTick } from "vue"
|
|
|
+import { useRoute, useRouter } from "vue-router"
|
|
|
+import { useStore } from "vuex"
|
|
|
+import useSmoothSwipe from "@/useFunctions/useSmoothSwipe.js"
|
|
|
+import { useWindowSize } from "@vueuse/core"
|
|
|
+import OperationTip from "@/components/OperationTip.vue"
|
|
|
+
|
|
|
+const route = useRoute()
|
|
|
+const router = useRouter()
|
|
|
+const store = useStore()
|
|
|
+
|
|
|
+const windowWidthDesign = 7681 * 2
|
|
|
+const windowHeightDesign = 1080 - 71 - 37 // 设计稿里视口高度。注意要减去上下边栏
|
|
|
+
|
|
|
+const scrollTarget = ref(null)
|
|
|
+const { width: windowWidth, height: windowHeight } = useWindowSize()
|
|
|
+
|
|
|
+const maxTranslateLength = computed(() => {
|
|
|
+ return (windowHeight.value * windowWidthDesign) / windowHeightDesign - 800 // 有的图层不够长导致移动到最右侧不好看,隐藏掉。
|
|
|
+})
|
|
|
+
|
|
|
+const {
|
|
|
+ translateLength,
|
|
|
+} = useSmoothSwipe({
|
|
|
+ scrollTargetRef: scrollTarget,
|
|
|
+ maxTranslateLength,
|
|
|
+ viewportWidth: windowWidth,
|
|
|
+})
|
|
|
+
|
|
|
+// layer4Left位移
|
|
|
+const layer4SpeedFactor = 0.6
|
|
|
+const layer4InitialLeft = 0
|
|
|
+const layer4Left = ref(layer4InitialLeft)
|
|
|
+
|
|
|
+// layer3Left位移
|
|
|
+const layer3SpeedFactor = 0.8
|
|
|
+const layer3InitialLeft = 0
|
|
|
+const layer3Left = ref(layer3InitialLeft)
|
|
|
+
|
|
|
+// layer2Left位移
|
|
|
+const layer2SpeedFactor = 1
|
|
|
+const layer2InitialLeft = 0
|
|
|
+const layer2Left = ref(layer2InitialLeft)
|
|
|
+
|
|
|
+// layer1Left位移
|
|
|
+const layer1InitialLeft = 0
|
|
|
+const layer1Left = ref(layer1InitialLeft)
|
|
|
+
|
|
|
+watch(
|
|
|
+ translateLength,
|
|
|
+ (v) => {
|
|
|
+ layer4Left.value = layer4InitialLeft - v * layer4SpeedFactor
|
|
|
+ layer3Left.value = layer3InitialLeft - v * layer3SpeedFactor
|
|
|
+ layer2Left.value = layer2InitialLeft - v * layer2SpeedFactor
|
|
|
+ layer1Left.value = layer1InitialLeft - v
|
|
|
+ },
|
|
|
+ {
|
|
|
+ immediate: true,
|
|
|
+ }
|
|
|
+)
|
|
|
+
|
|
|
+const poemList = configExcel["诗词"]
|
|
|
+
|
|
|
+const ageList = [
|
|
|
+ {
|
|
|
+ name: '唐',
|
|
|
+ id: 'tang',
|
|
|
+ startPos: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '宋',
|
|
|
+ id: 'song',
|
|
|
+ startPos: 3000,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '元',
|
|
|
+ id: 'yuan',
|
|
|
+ startPos: 5500,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '明',
|
|
|
+ id: 'ming',
|
|
|
+ startPos: 8500
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '清',
|
|
|
+ id: 'qing',
|
|
|
+ startPos: 11200
|
|
|
+ },
|
|
|
+]
|
|
|
+
|
|
|
+function onClickAge(item) {
|
|
|
+ translateLength.value = item.startPos * windowHeight.value / windowHeightDesign
|
|
|
+}
|
|
|
+const activeAgeIdx = ref(0)
|
|
|
+watch(translateLength, (v) => {
|
|
|
+ for (let index = ageList.length - 1; index >= 0; index--) {
|
|
|
+ const element = ageList[index]
|
|
|
+ if (element.startPos * windowHeight.value / windowHeightDesign <= translateLength.value ) {
|
|
|
+ activeAgeIdx.value = index
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="less" scoped>
|
|
|
+.poem-list {
|
|
|
+ background-color: #fefefe;
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ top: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ user-select: none;
|
|
|
+
|
|
|
+ > .scroll-target {
|
|
|
+ height: 100%;
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ gap: 100px;
|
|
|
+ overflow: hidden;
|
|
|
+
|
|
|
+ > .layer-4 {
|
|
|
+ position: absolute;
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ > .bg {
|
|
|
+ flex: 0 0 auto;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ > .layer-3 {
|
|
|
+ position: absolute;
|
|
|
+ height: 33%;
|
|
|
+ bottom: 0;
|
|
|
+ display: flex;
|
|
|
+ > .bamboo {
|
|
|
+ flex: 0 0 auto;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ > .bamboo:nth-of-type(1){
|
|
|
+ margin-left: calc((1250px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ > .bamboo:nth-of-type(2){
|
|
|
+ margin-left: calc((171px + 1250px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ > .layer-2 {
|
|
|
+ position: absolute;
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ > .bamboo {
|
|
|
+ flex: 0 0 auto;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ > .bamboo:nth-of-type(1){
|
|
|
+ margin-left: calc((193px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ > .bamboo:nth-of-type(2){
|
|
|
+ margin-left: calc((720px + 193px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ > .layer-1 {
|
|
|
+ position: absolute;
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ > .bamboo {
|
|
|
+ flex: 0 0 auto;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ > .bamboo:nth-of-type(1){
|
|
|
+ margin-left: calc((418px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ > .bamboo:nth-of-type(2){
|
|
|
+ margin-left: calc((800px + 418px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ >.poem {
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ top: 10.1%;
|
|
|
+ writing-mode: vertical-rl;
|
|
|
+ > .title-wrap {
|
|
|
+ position: relative;
|
|
|
+ width: fit-content;
|
|
|
+ height: fit-content;
|
|
|
+ > h1 {
|
|
|
+ font-family: KingHwa_OldSong, KingHwa_OldSong;
|
|
|
+ font-weight: 400;
|
|
|
+ font-size: calc(48px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ color: #303030;
|
|
|
+ line-height: calc(56px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ white-space: pre;
|
|
|
+ }
|
|
|
+ > .sub-title {
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ top: 50%;
|
|
|
+ transform: translate(-140%, -50%);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ > .author {
|
|
|
+ white-space: pre;
|
|
|
+ font-family: KaiTi;
|
|
|
+ font-weight: 400;
|
|
|
+ font-size: calc(24px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ color: #BAA565;
|
|
|
+ margin-inline-end: 0.5em;
|
|
|
+ }
|
|
|
+ > .age {
|
|
|
+ display: inline-block;
|
|
|
+ width: calc(24px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ height: calc(24px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ background-color: #b6a261;
|
|
|
+ border-radius: 50%;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ font-family: KaiTi;
|
|
|
+ font-weight: 400;
|
|
|
+ font-size: calc(20px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ color: #ffffff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ > p {
|
|
|
+ position: absolute;
|
|
|
+ right: calc(120px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ top: 75%;
|
|
|
+ font-family: KaiTi;
|
|
|
+ font-weight: 400;
|
|
|
+ font-size: calc(26px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ color: #303030;
|
|
|
+ line-height: 1.6em;
|
|
|
+ white-space: pre;
|
|
|
+ letter-spacing: 0.2em;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(1) {
|
|
|
+ top: calc(210px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ left: calc(260px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(2) {
|
|
|
+ left: calc(830px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(3) {
|
|
|
+ left: calc(1700px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(4) {
|
|
|
+ left: calc(2500px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(5) {
|
|
|
+ left: calc(3550px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ >p{
|
|
|
+ transform: translateY(-15%);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(6) {
|
|
|
+ left: calc(3950px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(7) {
|
|
|
+ left: calc(4300px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(8) {
|
|
|
+ left: calc(5100px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(9) {
|
|
|
+ left: calc(6000px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ >p{
|
|
|
+ transform: translateY(-12%);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(10) {
|
|
|
+ left: calc(6800px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(11) {
|
|
|
+ transform: translateY(40%);
|
|
|
+ left: calc((7200px + 260px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(12) {
|
|
|
+ left: calc((7200px + 830px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ >p{
|
|
|
+ transform: translateY(-40%);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(13) {
|
|
|
+ left: calc((7200px + 1700px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(14) {
|
|
|
+ left: calc((7200px + 2500px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(15) {
|
|
|
+ left: calc((7200px + 3550px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(16) {
|
|
|
+ left: calc((7200px + 3950px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(17) {
|
|
|
+ left: calc((7200px + 4300px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(18) {
|
|
|
+ left: calc((7200px + 5100px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(19) {
|
|
|
+ transform: translateY(-10%);
|
|
|
+ left: calc((7200px + 6000px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ >p{
|
|
|
+ transform: translateY(-80%);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .poem:nth-of-type(20) {
|
|
|
+ left: calc((7200px + 6800px) * v-bind('windowHeight') / v-bind('windowHeightDesign'));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ >.shadow-bottom{
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ bottom: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 12.4%;
|
|
|
+ background: linear-gradient(0deg, #888 0%, rgba(0,0,0,0) 100%);
|
|
|
+ >menu.age-list{
|
|
|
+ position: absolute;
|
|
|
+ left: 50%;
|
|
|
+ bottom: 30px;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 20px;
|
|
|
+ >button.age{
|
|
|
+ width: 47px;
|
|
|
+ height: 47px;
|
|
|
+ position: relative;
|
|
|
+ >img{
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ top: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ >img.img-normal{
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+ >img.img-active{
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ >button.age:hover, button.age.active{
|
|
|
+ >img.img-normal{
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+ >img.img-active{
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ > .operation-tip {
|
|
|
+ position: absolute;
|
|
|
+ right: calc(
|
|
|
+ 44 / v-bind("windowSizeWhenDesignForRef") *
|
|
|
+ v-bind("windowSizeInCssForRef")
|
|
|
+ );
|
|
|
+ bottom: calc(
|
|
|
+ 74 / v-bind("windowSizeWhenDesignForRef") *
|
|
|
+ v-bind("windowSizeInCssForRef")
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|