<template>
  <div
    class="home"
    @mousedown="onMouseDown"
    @mousemove="onMouseMove"
    @mouseup="onMouseUp"
    @mouseleave="onMouseLeave"
    @wheel.passive="onWheel"
    @dragstart.prevent
  >
    <div
      ref="landscape-wrap"
      class="landscape-wrap"
      :style="{
        left: landscapePositionleft,
      }"
    >
      <img
        v-for="index in 3"
        :key="index"
        class="landscape"
        src="@/assets/landscape.png"
        alt=""
        @dragstart.prevent
      >
    </div>
    <div
      class="people-far-wrap"
      :style="{
        right: peopleFarPositionRight,
      }"
    >
      <img
        class="people-far"
        :class="peopleFarColorStatus"
        src="@/assets/people-far-serial-frame-400-600-60.png"
        alt=""
        @dragstart.prevent
      >
      <HotSpot
        v-if="[3].includes(tourState) || ([0].includes(tourState) && maskOpacity === 0)"
        class="hot-spot"
        @click="onClickPeopleFarHotSpot"
      />
    </div>
    <div
      class="people-near-wrap"
      :style="{
        left: peopleNearPositionLeft,
      }"
    >
      <img
        class="people-near"
        src="@/assets/people-near.png"
        alt=""
        @dragstart.prevent
      >
      <img
        v-show="[0, 1].includes(tourState)"
        ref="treasure"
        class="treasure"
        :style="{
          height: treasureInitialHeightPercent + '%',
          opacity: treasureOpacity,
        }"
        src="@/assets/treasure.png"
        alt=""
        @dragstart.prevent
      >
    </div>
    <img
      class="introduce"
      :style="{
        left: introducePositionLeft,
      }"
      src="@/assets/introduce.png"
      alt=""
      @dragstart.prevent
    >

    <div
      v-if="[0, 1, 2].includes(tourState) && maskOpacity !== 0"
      class="fade-mask"
      :style="{
        opacity: maskOpacity,
      }"
    >
      <img
        v-show="[2].includes(tourState)"
        src="@/assets/treasure-last-frame.jpg"
        alt=""
      >
    </div>

    <div
      v-show="[1].includes(tourState)"
      class="treasure-frames-wrap"
    >
      <img
        v-for="index of treasureFrameTotalNum"
        v-show="treasureFrameCurNum === index - 1 ||
          treasureFrameCurNum - 1 === index - 1
        "
        :key="index"
        class="treasure-frame"
        :src="require(`@/assets/treasure-frames/合成 1_${(index-1).toString().padStart(5, '0')}.jpg`)"
        alt=""
        @load="onTreasureFrameLoad(index - 1)"
        @error="onTreasureFrameError(index - 1)"
      >
      <div
        class="text1"
        :style="{opacity: text1Opacity}"
      >
        <span class="title">宋清瓷团花粉盒</span><br>
        <span>约公元前1220年<br>口径13.5cm  底径8cm  高6cm</span>
      </div>
      <div
        class="text2"
        :style="{opacity: text2Opacity}"
      >
        此展品为宋代文物。子母口，浅腹，平底，盖面平；盒为子口，内有三个小碟；胎灰白，坚硬，施青色釉，口沿与底部无釉。现收藏于松阳县博物馆。
      </div>
    </div>
  </div>
</template>

<script>
const initialPeopleNearPositionLeft = '25%'
const initPeopleFarPositionRight = '10%'
const landscapeSpeedRate = 0.02
const peopleFarSpeedRate = 0.4
const peopleNearSpeedRate = 0.6
const introduceSpeedRate = 0.6
const treasureFadeInProgressRightBorder = 3000
const treasureDisplayProgressRightBorder = 6000
const treasureFadeOutProgressRightBorder = 2000
const translateLengthRightBorder = 900
const treasureFrameTotalNum = 125
const treasureInitialHeightPercent = 9
const treasureFinalHeightPercent = 116

export default {
  name: 'HomeView',
  components: {
  },
  data() {
    return {
      // 鼠标拖拽相关
      isMouseDown: false,
      lastMoveEventTimeStamp: 0,
      moveSpeed: 0,

      // 动画帧相关
      lastAnimationTimeStamp: 0,
      animationFrameId: null,

      tourState: 0, // 0:文物淡入过渡阶段；1:文物三维展示阶段；2：文物渐出过渡阶段；3：镜头平移阶段

      // 镜头平移相关
      translateLength: 0,
      landscapePositionleft: '18.491%',
      peopleFarPositionRight: initPeopleFarPositionRight,
      peopleNearPositionLeft: initialPeopleNearPositionLeft,
      introducePositionLeft: '3.347%',

      // 文物淡入相关
      treasureFadeInProgress: 0,
      treasureFadeInProgressRightBorder,
      treasureFadeInInitialLeft: 0,
      treasureFadeInInitialTop: 0,
      treasureFadeInFinalLeft: 0,
      treasureFadeInFinalTop: 0,
      treasureInitialHeightPercent,

      // 文物展示相关
      treasureDisplayProgress: 0,
      treasureFrameTotalNum,
      treasureFrameCurNum: 0,
      treasureFrameStateList: new Array(treasureFrameTotalNum),

      // 文物淡出相关
      treasureFadeOutProgress: 0,
      treasureFadeOutProgressRightBorder,

      // 远处人物变色相关
      peopleFarColorStatus: 'no-color', // 'no-color', 'color'
      isPeopleFarColorChanging: false,
    }
  },
  computed: {
    treasureOpacity() {
      if (this.tourState === 0) {
        if (this.treasureFadeInProgress > treasureFadeInProgressRightBorder / 2) {
          return 1
        } else {
          return this.treasureFadeInProgress / (treasureFadeInProgressRightBorder / 2)
        }
      } else if (this.tourState === 2) {
        if (this.treasureFadeOutProgress < treasureFadeOutProgressRightBorder / 2) {
          return 1
        } else {
          return 1 - (this.treasureFadeOutProgress - treasureFadeOutProgressRightBorder / 2) / (treasureFadeOutProgressRightBorder / 2)
        }
      } else {
        return 0
      }
    },
    maskOpacity() {
      if (this.tourState === 0) {
        if (this.treasureFadeInProgress > treasureFadeInProgressRightBorder / 2) {
          return 1
        } else {
          return this.treasureFadeInProgress / (treasureFadeInProgressRightBorder / 2)
        }
      } else if (this.tourState === 2) {
        if (this.treasureFadeOutProgress < treasureFadeOutProgressRightBorder / 2) {
          return 1
        } else {
          return 1 - (this.treasureFadeOutProgress - treasureFadeOutProgressRightBorder / 2) / (treasureFadeOutProgressRightBorder / 2)
        }
      } else {
        return 1
      }
    },
    text1Opacity() {
      if (this.tourState === 1) {
        if (this.treasureDisplayProgress < treasureDisplayProgressRightBorder * 0.1) {
          return this.treasureDisplayProgress / (treasureDisplayProgressRightBorder * 0.1)
        } else if (this.treasureDisplayProgress >= treasureDisplayProgressRightBorder * 0.1 && this.treasureDisplayProgress < treasureDisplayProgressRightBorder * 0.4) {
          return 1
        } else if (this.treasureDisplayProgress >= treasureDisplayProgressRightBorder * 0.4 && this.treasureDisplayProgress < treasureDisplayProgressRightBorder * 0.5) {
          return 1 - (this.treasureDisplayProgress - treasureDisplayProgressRightBorder * 0.4) / (treasureDisplayProgressRightBorder * (0.5 - 0.4))
        } else {
          return 0
        }
      } else {
        return 0
      }
    },
    text2Opacity() {
      if (this.tourState === 1) {
        if (this.treasureDisplayProgress < treasureDisplayProgressRightBorder * 0.5) {
          return 0
        } else if (this.treasureDisplayProgress >= treasureDisplayProgressRightBorder * 0.5 && this.treasureDisplayProgress < treasureDisplayProgressRightBorder * 0.6) {
          return (this.treasureDisplayProgress - treasureDisplayProgressRightBorder * 0.5) / (treasureDisplayProgressRightBorder * (0.6 - 0.5))
        } else if (this.treasureDisplayProgress >= treasureDisplayProgressRightBorder * 0.6 && this.treasureDisplayProgress < treasureDisplayProgressRightBorder * 0.9) {
          return 1
        } else {
          return 1 - (this.treasureDisplayProgress - treasureDisplayProgressRightBorder * 0.9) / (treasureDisplayProgressRightBorder * (1 - 0.9))
        }
      } else {
        return 0
      }
    },
  },
  watch: {
    tourState(vNew, vOld) {
      if (vOld === 0 && vNew === 1) {
        this.treasureDisplayProgress += 0.001
      } else if (vOld === 1 && vNew === 2) {
        this.treasureFadeOutProgress += 0.001
      } else if (vOld === 2 && vNew === 3) {
        this.translateLength -= 0.001
      } else if (vOld === 3 && vNew === 2) {
        this.treasureFadeOutProgress -= 0.001
      } else if (vOld === 2 && vNew === 1) {
        this.treasureDisplayProgress -= 0.001
      } else if (vOld === 1 && vNew === 0) {
        this.treasureFadeInProgress -= 0.001
      }
    },
    treasureFadeInProgress: {
      handler(vNew, vOld) {
        if (vOld < this.treasureFadeInProgressRightBorder && vNew >= this.treasureFadeInProgressRightBorder && this.tourState === 0) {
          this.tourState = 1
        }
        if (this.treasureFadeInProgress > treasureFadeInProgressRightBorder / 2) {
          this.$refs.treasure.style.left = this.treasureFadeInInitialLeft + (this.treasureFadeInProgress - treasureFadeInProgressRightBorder / 2) / (treasureFadeInProgressRightBorder / 2) * (this.treasureFadeInFinalLeft - this.treasureFadeInInitialLeft) + 'px'
          this.$refs.treasure.style.top = this.treasureFadeInInitialTop + (this.treasureFadeInProgress - treasureFadeInProgressRightBorder / 2) / (treasureFadeInProgressRightBorder / 2) * (this.treasureFadeInFinalTop - this.treasureFadeInInitialTop) + 'px'
          this.$refs.treasure.style.transform = `translate(-50%, -50%) scale(${1 + (this.treasureFadeInProgress - treasureFadeInProgressRightBorder / 2) / (treasureFadeInProgressRightBorder / 2) * (treasureFinalHeightPercent / this.treasureInitialHeightPercent - 1)})`
        } else {
          this.$refs.treasure.style.left = this.treasureFadeInInitialLeft + 'px'
          this.$refs.treasure.style.top = this.treasureFadeInInitialTop + 'px'
          this.$refs.treasure.style.transform = `translate(-50%, -50%) scale(1)`
        }
      }
    },
    treasureDisplayProgress: {
      handler(vNew, vOld) {
        // 更新toureState
        if (vOld > 0 && vNew <= 0 && this.tourState === 1) {
          this.tourState = 0
        } else if (vOld < treasureDisplayProgressRightBorder && vNew >= treasureDisplayProgressRightBorder && this.tourState === 1) {
          this.tourState = 2
        }

        let idealCurNum = Math.round(this.treasureDisplayProgress / treasureDisplayProgressRightBorder * treasureFrameTotalNum)

        while (this.treasureFrameStateList[idealCurNum] === false) {
          idealCurNum--
        }
        this.treasureFrameCurNum = idealCurNum
      }
    },
    treasureFadeOutProgress: {
      handler(vNew, vOld) {
        if (vOld > 0 && vNew <= 0 && this.tourState === 2) {
          this.tourState = 1
        } else if (vOld < this.treasureFadeOutProgressRightBorder && vNew >= this.treasureFadeOutProgressRightBorder && this.tourState === 2) {
          this.tourState = 3
        }
      }
    },
    translateLength: {
      handler(vNew, vOld) {
        // const rightBorder = window.innerWidth * 2

        if (vOld < 0 && vNew >= 0 && this.tourState === 3) {
          this.tourState = 2
        }
        // if (vOld > -rightBorder && vNew <= -rightBorder && this.tourState === 3) {
        //   this.tourState = 1
        // }

        this.landscapePositionleft = `calc(18.491% + ${vNew * landscapeSpeedRate}px)`
        this.peopleFarPositionRight = `calc(${initPeopleFarPositionRight} - ${vNew * peopleFarSpeedRate}px)`
        this.peopleNearPositionLeft = `calc(${initialPeopleNearPositionLeft} + ${vNew * peopleNearSpeedRate}px)`
        this.introducePositionLeft = `calc(3.347% + ${vNew * introduceSpeedRate}px)`
      }
    },
  },
  mounted() {
    this.animationFrameId = requestAnimationFrame(this.inertanceEffect)
    setTimeout(() => {
      this.treasureFadeInInitialLeft = this.$refs.treasure.offsetLeft
      this.treasureFadeInInitialTop = this.$refs.treasure.offsetTop
      this.treasureFadeInFinalLeft = window.innerWidth / 2 - this.$refs.treasure.offsetParent.offsetLeft
      this.treasureFadeInFinalTop = window.innerHeight / 2 - this.$refs.treasure.offsetParent.offsetTop
    }, 100)
  },
  unmounted() {
    cancelAnimationFrame(this.animationFrameId)
  },
  methods: {
    onMouseDown(e) {
      this.isMouseDown = true
      this.moveSpeed = 0
      this.lastMoveEventTimeStamp = 0
      this.lastAnimationTimeStamp = Date.now()
    },
    onMouseUp(e) {
      this.isMouseDown = false
    },
    onMouseLeave() {
      this.isMouseDown = false
    },
    onMouseMove(e) {
      if (this.isMouseDown) {
        if (this.lastMoveEventTimeStamp) {
          // 更新speed
          const currentMoveSpeed = e.movementX / (e.timeStamp - this.lastMoveEventTimeStamp)
          this.moveSpeed = this.moveSpeed * 0.9 + currentMoveSpeed * 0.1
        }
        this.lastMoveEventTimeStamp = e.timeStamp
      }
    },
    onWheel(e) {
      if (this.tourState === 0) {
        this.treasureFadeInProgress += e.deltaY
        if (this.treasureFadeInProgress < 0) {
          this.treasureFadeInProgress = 0
          this.moveSpeed = 0
        } else if (this.treasureFadeInProgress > this.treasureFadeInProgressRightBorder) {
          this.treasureFadeInProgress = this.treasureFadeInProgressRightBorder
        }
      } else if (this.tourState === 1) {
        this.treasureDisplayProgress += e.deltaY
        if (this.treasureDisplayProgress < 0) {
          this.treasureDisplayProgress = 0
        } else if (this.treasureDisplayProgress > treasureDisplayProgressRightBorder) {
          this.treasureDisplayProgress = treasureDisplayProgressRightBorder
        }
      } else if (this.tourState === 2) {
        this.treasureFadeOutProgress += e.deltaY
        if (this.treasureFadeOutProgress < 0) {
          this.treasureFadeOutProgress = 0
        } else if (this.treasureFadeOutProgress > this.treasureFadeOutProgressRightBorder) {
          this.treasureFadeOutProgress = this.treasureFadeOutProgressRightBorder
        }
      } else if (this.tourState === 3) {
        this.translateLength -= e.deltaY
        if (this.translateLength > 0) {
          this.translateLength = 0
        } else if (this.translateLength < -translateLengthRightBorder) {
          this.translateLength = -translateLengthRightBorder
          this.moveSpeed = 0
        }
      }
    },
    inertanceEffect() {
      const timeStamp = Date.now()
      const timeElapsed = timeStamp - this.lastAnimationTimeStamp

      // 速度减慢
      if (this.moveSpeed > 0) {
        this.moveSpeed -= 0.003 * timeElapsed
        if (this.moveSpeed < 0) {
          this.moveSpeed = 0
        }
      } else if (this.moveSpeed < 0) {
        this.moveSpeed += 0.003 * timeElapsed
        if (this.moveSpeed > 0) {
          this.moveSpeed = 0
        }
      }

      // 根据速度更新“距离”
      if (this.tourState === 0) {
        this.treasureFadeInProgress -= this.moveSpeed * timeElapsed
        if (this.treasureFadeInProgress < 0) {
          this.treasureFadeInProgress = 0
          this.moveSpeed = 0
        } else if (this.treasureFadeInProgress > this.treasureFadeInProgressRightBorder) {
          this.treasureFadeInProgress = this.treasureFadeInProgressRightBorder
        }
      } else if (this.tourState === 1) {
        this.treasureDisplayProgress -= this.moveSpeed * timeElapsed
        if (this.treasureDisplayProgress < 0) {
          this.treasureDisplayProgress = 0
        } else if (this.treasureDisplayProgress > treasureDisplayProgressRightBorder) {
          this.treasureDisplayProgress = treasureDisplayProgressRightBorder
        }
      } else if (this.tourState === 2) {
        this.treasureFadeOutProgress -= this.moveSpeed * timeElapsed
        if (this.treasureFadeOutProgress < 0) {
          this.treasureFadeOutProgress = 0
        } else if (this.treasureFadeOutProgress > this.treasureFadeOutProgressRightBorder) {
          this.treasureFadeOutProgress = this.treasureFadeOutProgressRightBorder
        }
      } else if (this.tourState === 3) {
        this.translateLength += this.moveSpeed * timeElapsed
        if (this.translateLength > 0) {
          this.translateLength = 0
        } else if (this.translateLength < -translateLengthRightBorder) {
          this.translateLength = -translateLengthRightBorder
          this.moveSpeed = 0
        }
      }

      this.lastAnimationTimeStamp = timeStamp
      this.animationFrameId = requestAnimationFrame(this.inertanceEffect)
    },
    onClickPeopleFarHotSpot() {
      if (this.isPeopleFarColorChanging) {
        return
      } else {
        if (this.peopleFarColorStatus === 'no-color') {
          this.peopleFarColorStatus = 'color'
        } else {
          this.peopleFarColorStatus = 'no-color'
        }
        this.isPeopleFarColorChanging = true
        setTimeout(() => {
          this.isPeopleFarColorChanging = false
        }, 2500)
      }
    },
    onTreasureFrameLoad(idx) {
      this.treasureFrameStateList[idx] = true
    },
    onTreasureFrameError(idx) {
      this.treasureFrameStateList[idx] = false
    },
  }
}
</script>

<style lang="less" scoped>
.home {
  width: 100%;
  height: 100%;
  background-image: url(@/assets/background.jpg);
  background-repeat: repeat;
  background-size: contain;
  position: relative;
  overflow: hidden;
  .landscape-wrap {
    position: absolute;
    height: 30%;
    top: 0;
    display: flex;
    > .landscape {
      height: 100%;
    }
  }
  > .people-far-wrap {
    position: absolute;
    top: 20%;
    height: 630px;
    width: 420px;
    overflow: hidden;
    > .people-far {
      position: absolute;
      height: 100%;
      transition-property: left;
      transition-duration: 2.5s;
      transition-timing-function: steps(59, jump-end);
      &.no-color {
        left: 0;
      }
      &.color {
        left: calc(-100% * 59)
      }
    }
    > .hot-spot {
      position: absolute;
      left: 52%;
      transform: translateX(-50%);
      top: 17%;
    }
  }
  > .people-near-wrap {
    position: absolute;
    bottom: -13%;
    height: 100vh;
    > .people-near {
      height: 100%;
    }
    > .treasure {
      position: absolute;
      left: 49%;
      top: 32.5%;
      z-index: 2;
      transform: translate(-50%, -50%);
    }
  }
  .introduce {
    position: absolute;
    top: 5%;
    width: 13.727%;
  }
  .fade-mask {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: #bfbfa7;
    z-index: 1;
    img {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
  }
  .treasure-frames-wrap {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 3;
    > img {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
    > .text1 {
      color: #fff;
      position: absolute;
      top: 5%;
      left: 3%;
      .title {
        font-size: 24px;
        font-weight: bold;
        line-height: 2;

      }
      span {
        font-size: 18px;
        line-height: 1.5;
      }
    }
    > .text2 {
      color: #fff;
      position: absolute;
      bottom: 5%;
      right: 3%;
      width: 30%;
      font-size: 18px;
      line-height: 1.5;
    }
  }
  @media screen and (max-height: 810px) {
    .people-far-wrap {
      height: 540px;
      width: 360px;
    }
  }
  @media screen and (max-height: 720px) {
    .people-far-wrap {
      height: 480px;
      width: 320px;
    }
  }
  @media screen and (max-height: 630px) {
    .people-far-wrap {
      height: 420px;
      width: 280px;
    }
  }
  @media screen and (max-height: 540px) {
    .people-far-wrap {
      height: 360px;
      width: 240px;
    }
  }
}
</style>