123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625 |
- <template>
- <div style="height: 100%">
- <div
- v-if="hotVisible"
- class="bamboo-hot2-hot"
- :class="{
- left: [7, 8].includes(checkedHotId)
- }"
- >
- <div class="bamboo-hot2-hot__title">
- {{ ITEM_INFO_MAP[checkedHotId].label }}
- </div>
- <p
- class="bamboo-hot2-hot__inner"
- >
- {{ ITEM_INFO_MAP[checkedHotId].info }}
- </p>
- </div>
- <div
- ref="bambooWrap"
- class="bamboo-hot2"
- :class="{
- 'wrap-hide': hotVisible
- }"
- @touchstart="handleTouchstart"
- @touchmove="handleTouchmove"
- @touchend="handleTouchend"
- >
- <div
- class="bamboo-hot2-b1"
- :class="{
- hide: hotVisible && checkedHotId !== 1
- }"
- >
- <img src="./images/bamboo1.png">
- <div
- class="bamboo-hot2__hot"
- :class="{
- hide: hotVisible
- }"
- @click="handleHot(1)"
- >
- <p>水竹</p>
- </div>
- </div>
- <div
- class="bamboo-hot2-b2"
- :class="{
- hide: hotVisible && checkedHotId !== 2
- }"
- >
- <img
- src="./images/bamboo2.png"
- @load="handleBambooOffset(2)"
- >
- </div>
- <div
- class="bamboo-hot2__hot b2"
- :class="{
- hide: hotVisible
- }"
- @click="handleHot(2)"
- >
- <p>紫竹</p>
- </div>
- <div
- class="bamboo-hot2-b3"
- :class="{
- hide: hotVisible && checkedHotId !== 3
- }"
- >
- <img
- src="./images/bamboo3.png"
- @load="handleBambooOffset(3)"
- >
- </div>
- <div
- class="bamboo-hot2__hot b3"
- :class="{
- hide: hotVisible
- }"
- @click="handleHot(3)"
- >
- <p>梅鹿竹</p>
- </div>
- <div
- class="bamboo-hot2-b4"
- :class="{
- hide: hotVisible && checkedHotId !== 4
- }"
- >
- <img
- src="./images/bamboo4.png"
- @load="handleBambooOffset(4)"
- >
- <div
- class="bamboo-hot2__hot"
- :class="{
- hide: hotVisible
- }"
- @click="handleHot(4)"
- >
- <p>楠竹</p>
- </div>
- </div>
- <div
- class="bamboo-hot2-b7"
- :class="{
- hide: hotVisible && checkedHotId !== 7
- }"
- >
- <img
- src="./images/bamboo7.png"
- @load="handleBambooOffset(7)"
- >
- </div>
- <div
- class="bamboo-hot2__hot b7"
- :class="{
- hide: hotVisible
- }"
- @click="handleHot(7)"
- >
- <p>湘妃竹</p>
- </div>
- <div
- class="bamboo-hot2-b8"
- :class="{
- hide: hotVisible && checkedHotId !== 8
- }"
- >
- <img
- src="./images/bamboo8.png"
- @load="handleBambooOffset(8)"
- >
- <div
- class="bamboo-hot2__hot"
- :class="{
- hide: hotVisible
- }"
- @click="handleHot(8)"
- >
- <p>单竹</p>
- </div>
- </div>
- <div
- ref="bambooWrapBg"
- class="bamboo-hot2-bg-wrap"
- >
- <img
- v-if="bgImgLoaded"
- class="bamboo-hot2__grass"
- :class="{
- hide: hotVisible
- }"
- src="./images/grass.png"
- >
- <img
- class="bamboo-hot2__bg"
- src="./images/bg.png"
- :style="{
- filter: hotVisible ? 'saturate(1.3) brightness(0.95)' : 'none'
- }"
- @load="bgImgLoaded = true"
- >
- </div>
- </div>
- <div class="system-btns">
- <BtnBack @click="goBack" />
- <OperationTip
- id="operationH"
- class="operation-h"
- text=""
- direction="h"
- />
- </div>
- </div>
- </template>
- <script setup>
- import { ref, watch, onBeforeUnmount } from 'vue'
- import { useRouter } from 'vue-router'
- import useSizeAdapt from "@/useFunctions/useSizeAdapt"
- let itemScrollMap = {
- 1: 0,
- 2: 0,
- 3: 0,
- 4: 450,
- 7: 0,
- 8: 1048,
- }
- const ITEM_INFO_MAP = {
- 1: {
- label: '水竹',
- info: '篷耳小,形状为卵形或长椭圆形。锋舌边缘生有短白纤毛。筝片直立,呈三角形至狭长三角形。'
- },
- 2: {
- label: '紫竹',
- info: '紫竹幼竿绿色,覆盖细柔毛和白粉,幕环有毛,籍鞘背面红褐色或绿色加深。叶片小而薄,窄披针形。'
- },
- 3: {
- label: '梅鹿竹',
- info: '梅鹿竹斑纹相连,圆形,外轮廓深色,斑心发白。竹地上有兽斑状斑痕,酷似梅花鹿的花纹。'
- },
- 4: {
- label: '楠竹',
- info: '单轴散生型常绿乔木状竹类植物,呈直立状,竹叶深绿,呈披针形'
- },
- 7: {
- label: '湘妃竹',
- info: '中小型竹,竿环及箨(tuò)环隆起,竿箨黄褐色,有黑褐色斑点,箨叶三角形或带形'
- },
- 8: {
- label: '单竹',
- info: '竹质细腻,纤维韧性极强,可制成薄如蝉翼的竹篾丝,编织成绸似、绢似的精美竹编工艺品。'
- },
- }
- const bgImgLoaded = ref(false)
- const {
- windowSizeInCssForRef,
- windowSizeWhenDesignForRef,
- } = useSizeAdapt()
- const router = useRouter()
- const bambooWrap = ref()
- const bambooWrapBg = ref()
- const hotVisible = ref(false)
- const checkedHotId = ref(0)
- const handleHot = (id) => {
- checkedHotId.value = id
- hotVisible.value = true
- cancelAnimationFrame(animationFrameId.value)
- bambooWrap.value.scrollTo({
- left: itemScrollMap[id],
- behavior: 'smooth'
- })
- translateX.value = itemScrollMap[id]
- }
- const handleBambooOffset = (target) => {
- let temp = 0
- if ([7, 8].includes(target)) {
- if (target === 7) {
- temp = window.innerWidth * 0.2
- } else {
- temp = window.innerWidth * 0.2
- }
- itemScrollMap[target] = maxTranslateXLength - temp
- return
- }
- const offset = window.innerWidth / 6
- const left = document.getElementsByClassName(`bamboo-hot2-b${target}`)?.[0].getBoundingClientRect().left
- switch (target) {
- case 3:
- temp = window.innerWidth / 3
- break
- case 4:
- temp = -(window.innerWidth * 0.25)
- break
- }
- itemScrollMap[target] = left - offset + temp
- }
- // 动画帧相关
- const lastAnimationTimeStamp = ref(0)
- const animationFrameId = ref(0)
- const moveSpeed = ref(0)
- const translateX = ref(0)
- const match = windowSizeInCssForRef.value.match(/\d+/)
- const maxTranslateXLength = (window.innerWidth * 3 - 150) / Number(windowSizeWhenDesignForRef.value) * parseInt(match[0], 10)
- const lastMoveEventTimeStamp = ref(0)
- const isMouseDown = ref(false)
- const isMove = ref(false)
- const lastTouchPos = ref(0)
- watch([bambooWrapBg, bgImgLoaded], () => {
- if (!bgImgLoaded.value) return
- animationFrameId.value = requestAnimationFrame(animationFrameTask)
- })
- const animationFrameTask = () => {
- const timeStamp = Date.now()
- const timeElapsed = timeStamp - lastAnimationTimeStamp.value
- // 速度减慢
- if (moveSpeed.value > 0) {
- moveSpeed.value -= 0.002 * timeElapsed
- if (moveSpeed.value < 0) {
- moveSpeed.value = 0
- }
- } else if (moveSpeed.value < 0) {
- moveSpeed.value += 0.002 * timeElapsed
- if (moveSpeed.value > 0) {
- moveSpeed.value = 0
- }
- }
- // 根据速度更新距离
- translateX.value += moveSpeed.value * timeElapsed
- if (translateX.value < 0) {
- translateX.value = 0
- } else if (translateX.value > maxTranslateXLength) {
- translateX.value = maxTranslateXLength
- moveSpeed.value = 0
- }
- bambooWrap.value?.scrollTo({
- left: translateX.value,
- behavior: 'instant'
- })
- lastAnimationTimeStamp.value = timeStamp
- animationFrameId.value = requestAnimationFrame(animationFrameTask)
- }
- const handleTouchstart = (e) => {
- if (hotVisible.value) return
- isMouseDown.value = true
- moveSpeed.value = 0
- lastMoveEventTimeStamp.value = 0
- lastAnimationTimeStamp.value = Date.now()
- lastTouchPos.value = e.changedTouches[0].clientX
- }
- const handleTouchmove = (e) => {
- e.preventDefault()
- if (hotVisible.value || !isMouseDown.value || !e.changedTouches.length) return
- if (
- lastMoveEventTimeStamp.value &&
- e.timeStamp - lastMoveEventTimeStamp.value > 1
- ) {
- // 更新speed
- isMove.value = true
- const currentMoveSpeed =
- (-(e.changedTouches[0].clientX - lastTouchPos.value) /
- (e.timeStamp - lastMoveEventTimeStamp.value)) *
- 1.5
- moveSpeed.value = moveSpeed.value * 0.9 + currentMoveSpeed * 0.1
- lastTouchPos.value = e.changedTouches[0].clientX
- }
- lastMoveEventTimeStamp.value = e.timeStamp
- }
- const handleTouchend = () => {
- if (hotVisible.value) return
- isMouseDown.value = false
- setTimeout(() => {
- isMove.value = false
- })
- }
- const goBack = () => {
- if (hotVisible.value) {
- hotVisible.value = false
- checkedHotId.value = 0
- animationFrameId.value = requestAnimationFrame(animationFrameTask)
- return
- }
- router.replace({
- name: 'MoreContent',
- query: {
- anchorIdx: 0,
- }
- })
- }
- onBeforeUnmount(() => {
- cancelAnimationFrame(animationFrameId.value)
- })
- </script>
- <style lang="less" scoped>
- ::-webkit-scrollbar {
- display: none;
- }
- img {
- pointer-events: none;
- }
- .hide {
- opacity: 0 !important;
- animation: none !important;
- }
- [class^="bamboo-hot2-b"] {
- position: absolute;
- top: 0;
- height: 100%;
- z-index: 3;
- img {
- height: 100%;
- }
- }
- .bamboo-hot2-hot {
- display: flex;
- position: fixed;
- top: 50%;
- right: calc(70 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- transform: translateY(-50%);
- color: white;
- font-family: KaiTi;
- writing-mode: vertical-rl;
- white-space: nowrap;
- z-index: 999;
- &.left {
- right: unset;
- left: calc(70 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- writing-mode: vertical-lr;
- .bamboo-hot2-hot__title::before {
- right: unset;
- left: calc(-5 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- }
- }
- &__title {
- position: relative;
- margin-bottom: calc(90 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- font-weight: bold;
- letter-spacing: 5px;
- font-size: calc(38 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- &::before {
- content: '';
- position: absolute;
- top: calc(-2 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- right: calc(25 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- width: calc(15 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- height: calc(15 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- border-radius: 50%;
- border: 1px solid #F8DD86;
- z-index: -1;
- }
- }
- &__inner {
- letter-spacing: 2px;
- white-space: pre-wrap;
- line-height: calc(40 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- font-size: calc(20 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- height: calc(400 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- }
- }
- .bamboo-hot2 {
- position: relative;
- width: 100%;
- height: 100%;
- perspective: calc(100 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- transform-style: preserve-3d;
- overflow-x: auto;
- > * {
- opacity: 1;
- transition: all linear .2s;
- }
- &__hot {
- display: flex;
- align-items: center;
- justify-content: center;
- position: absolute;
- color: white;
- font-size: 12px;
- font-family: KaiTi;
- writing-mode: vertical-rl;
- animation: breathing linear 2s infinite;
- &::before {
- content: '';
- display: block;
- margin-bottom: calc(5 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- width: 20px;
- height: 20px;
- background: url('./images/hot.png') no-repeat center / contain;
- }
- }
- &-b1 {
- left: calc(50 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- transform: translateZ(calc(20 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'))) scale(0.8);
- .bamboo-hot2__hot {
- top: calc(340 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- right: calc(40 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- }
- }
- &-b2 {
- left: calc(320 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- transform: translateZ(calc(10 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef')));
- z-index: 2;
- }
- .bamboo-hot2__hot.b2 {
- top: calc(180 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- left: calc(370 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- transform: translateZ(calc(10 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef')));
- z-index: 4;
- }
- &-b3 {
- left: calc(210 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- transform: translateZ(calc(20 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'))) scale(0.8);
- }
- .bamboo-hot2__hot.b3 {
- top: calc(310 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- left: calc(464 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- transform: translateZ(calc(20 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef')));
- z-index: 4;
- }
- &-b4 {
- left: calc(780 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- transform: translateZ(calc(15 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'))) scale(0.85);
- .bamboo-hot2__hot {
- top: calc(220 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- right: calc(14 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- }
- }
- &-b7 {
- left: calc(950 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- transform: translateZ(calc(10 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef')));
- z-index: 2;
- }
- .bamboo-hot2__hot.b7 {
- top: calc(160 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- left: calc(1230 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- transform: translateZ(calc(10 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef')));
- z-index: 4;
- }
- &-b8 {
- left: calc(1080 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- transform: translateZ(calc(25 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'))) scale(0.8);
- .bamboo-hot2__hot {
- top: calc(320 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- right: calc(110 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- }
- }
- &.wrap-hide {
- &::before,
- &::after {
- opacity: 0;
- }
- }
- &::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- width: calc(457 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- height: calc(330 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- background: url('./images/leaf.png') no-repeat center / contain;
- opacity: 1;
- transition: opacity linear .2s;
- z-index: 3;
- }
- &-bg-wrap {
- width: fit-content;
- height: 100%;
- position: relative;
- z-index: 1;
- }
- &__grass {
- position: absolute;
- left: 0;
- bottom: 0;
- width: 100%;
- z-index: 1;
- }
- &__bg {
- height: 100%;
- }
- }
- .system-btns {
- width: 100%;
- padding: 0 calc(20 / v-bind(windowSizeWhenDesignForRef) * v-bind(windowSizeInCssForRef));
- display: flex;
- // flex-direction: column;
- justify-content: flex-end;
- position: absolute;
- bottom: calc(60 /v-bind(windowSizeWhenDesignForRef) * v-bind(windowSizeInCssForRef));
- z-index: 2;
- .operation-h {
- width: calc(36 /v-bind('windowSizeWhenDesignForRef')* v-bind('windowSizeInCssForRef'));
- transition: opacity 0.5s ease-in-out;
- }
- }
- @keyframes breathing {
- 0% {
- opacity: 1;
- }
- 50% {
- opacity: 0.3;
- }
- 100% {
- opacity: 1;
- }
- }
- </style>
|