123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535 |
- <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
- color="green"
- @click="router.go('-1')"
- />
- <OperationTip
- v-show="isShowOperationTip"
- 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 * windowHeight.value / windowHeightDesign // 有的图层不够长导致移动到最右侧不好看,隐藏掉。
- })
- 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
- }
- }
- })
- const isShowOperationTip = ref(true)
- const unwatch = watch(translateLength, (v) => {
- if (v) {
- isShowOperationTip.value = false
- unwatch()
- }
- })
- </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%;
- }
- > .bg:nth-of-type(2) {
- transform: rotate3d(0, 1, 0, 180deg);
- }
- }
- > .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: calc(30px / v-bind('windowHeightDesign') * v-bind('windowHeight'));
- transform: translateX(-50%);
- display: flex;
- align-items: center;
- gap: calc(20px / v-bind('windowHeightDesign') * v-bind('windowHeight'));
- >button.age{
- width: calc(47px / v-bind('windowHeightDesign') * v-bind('windowHeight'));
- height: calc(47px / v-bind('windowHeightDesign') * v-bind('windowHeight'));
- 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;
- left: 42%;
- bottom: calc(234px * v-bind('windowHeight') / v-bind('windowHeightDesign'));
- transform: translateX(-50%);
- }
- }
- </style>
|