<template>
  <div
    class="custom-list"
    ref="scrollBody"
    @mouseenter="mouseenterFunc"
    @mouseleave="mouseleaveFunc"
    @mousewheel="mousewheelFunc"
  >
    <div
      class="list-body"
      :class="{
        'list-body2': isHorizontal
      }"
      ref="listBody"
      :style="{ transform: getScrollDistance }"
    >
      <slot></slot>
    </div>
    <div
      class="list-body"
      :class="{
        'list-body2': isHorizontal
      }"
      ref="tBody"
      v-if="isCanScroll"
      :style="{ transform: getScrollDistance }">
      <slot></slot>
    </div>

    <!-- <button @click="stop">stop</button>
    <button @click="start">start</button>
    <button @click="initData">result</button> -->
  </div>
</template>

<script>
export default {
  name: "XxSeamlessScroll",
  props: {
    steep: {
      //滚动速度
      type: Number,
      default: 1
    },
    scrollDirection: {
      //滚动方向
      type: String,
      default: "top"
    },
    isRoller: {
      //是否可以滑轮滚动
      type: Boolean,
      default: true
    },
    rollerScrollDistance: {
      //滑轮滚动的距离
      type: Number,
      default: 20
    },
    isHoverStop: {
      //鼠标经过停止
      type: Boolean,
      default: true
    },
    singleHeight: {
      //单步运动停止的高度(默认值0是无缝不停止的滚动) scrollDirection  => 'top'/'bottom'
      type: Number,
      default: 0
    },
    singleWidth: {
      //单步运动停止的宽度(默认值0是无缝不停止的滚动) scrollDirection  => 'left'/'right'
      type: Number,
      default: 0
    },
    waitTime: {
      //单步停止等待时间(默认值1000ms)
      type: Number,
      default: 1000
    },
    data: Array
  },
  computed: {
    isHorizontal() {
      return (
        this.scrollDirection === "left" || this.scrollDirection === "right"
      )
    },
    //获取滚动样式
    getScrollDistance() {
      let c
      if (!this.isHorizontal) {
        c = "translate(0px, " + this.scrollDistance + "px)"
      } else {
        c = "translate(" + this.scrollDistance + "px,0px)"
      }
      return c
    },
  },
  data() {
    return {
      timer: null, //滚动定时器
      scrollDistance: 0, //滚动距离
      tDom: "", //复制的容器
      bodyHeight: 0, //滚动容器高度
      bodyWidth: 0, //滚动容器宽度
      listHeight: 0, //列表高度
      listWidth: 0, //列表宽度
      isStop: true,
      animationFrame: null,
      isCanScroll: false,
      singleWaitTime: null //单行暂停定时器
    }
  },
  methods: {
    //判断是否可以滚动函数
    isScrollFunc() {
      this.bodyHeight = this.$refs.scrollBody.clientHeight
      this.bodyWidth = this.$refs.scrollBody.clientWidth
      this.listHeight = this.$refs.listBody.clientHeight
      this.listWidth = this.$refs.listBody.clientWidth

      if ((!this.isHorizontal && this.bodyHeight !== 0 && this.listHeight !== 0 && this.listHeight > this.bodyHeight) || (this.isHorizontal && this.bodyWidth !== 0 && this.listWidth !== 0 && this.listWidth > this.bodyWidth)) {
        return true
      } else {
        return false
      }
    },
    start() {
      let that = this
      that.isStop = false
      this.run()
    },
    run() {
      let that = this
      if (!that.isCanScroll) return

      //清空动画
      that.clearAnimation(that.animationFrame)

      that.animationFrame = window.requestAnimationFrame(() => {
        //滚动主逻辑函数
        let main = (listSize, bodySize) => {
          let scrollDistance = Math.abs(that.scrollDistance)
          if (that.scrollDistance < 0) {
            let cc = 2 * listSize - bodySize
            if (scrollDistance > cc) {
              that.scrollDistance = -(listSize - bodySize)
            }
          } else {
            that.scrollDistance = -listSize
          }
        }

        //根据滚动方向判断使用高度或宽度控制效果
        if (!that.isHorizontal) {
          main(that.listHeight, that.bodyHeight)
        } else {
          main(that.listWidth, that.bodyWidth)
        }
        let scrollDistance = that.scrollDistance
        //判断滚动值
        if (!that.isStop) {
          if (
            that.scrollDirection === "top" ||
            that.scrollDirection === "left"
          ) {
            scrollDistance -= that.steep
          } else if (
            that.scrollDirection === "bottom" ||
            that.scrollDirection === "right"
          ) {
            scrollDistance += that.steep
          }
          that.scrollDistance = scrollDistance
          if (that.singleWaitTime) clearTimeout(that.singleWaitTime)
          if (that.singleHeight) { //是否启动了单行暂停配置
            if (Math.abs(that.scrollDistance) % that.singleHeight < that.steep) { // 符合条件暂停waitTime
              that.singleWaitTime = setTimeout(() => {
                that.run()
              }, that.waitTime)
            } else {
              that.run()
            }
          } else if (that.singleWidth) {
            if (Math.abs(that.scrollDistance) % that.singleWidth < that.steep) { // 符合条件暂停waitTime
              that.singleWaitTime = setTimeout(() => {
                that.run()
              }, that.waitTime)
            } else {
              that.run()
            }
          } else {
            that.run()
          }
        }
      })
    },
    //停止滚动
    stop() {
      this.isStop = true
      if (this.singleWaitTime) clearTimeout(this.singleWaitTime)
      this.clearAnimation()
    },
    //初始化数值
    initData() {
      this.stop()
      this.$nextTick(() => {
        if (this.isScrollFunc()) {
          this.isCanScroll = true
          this.start()
        } else {
          this.isCanScroll = false
          this.scrollDistance = 0
        }
      })
    },

    clearAnimation() {
      if (this.animationFrame) {
        cancelAnimationFrame(this.animationFrame)
        this.animationFrame = null
      }
    },
    mouseenterFunc() {
      if (this.isHoverStop) this.stop()
    },
    mouseleaveFunc() {
      if (this.isHoverStop) this.start()
    },
    mousewheelFunc(e) {
      if (!this.isCanScroll || !this.isRoller) {
        return false
      }
      // //滚动方向为横向时禁用鼠标滚轮滚动
      // if (this.scrollDirection === "left" || this.scrollDirection === "right") {
      //   return;
      // }
      let dis = e.deltaY
      if (dis > 0) {
        this.scrollDistance -= this.rollerScrollDistance
      } else {
        this.scrollDistance += this.rollerScrollDistance
      }
      this.run()
    }
  },
  watch: {
    data: {
      handler() {
        this.initData()
      },
      deep: true
    }
  },

  beforeMount() { },
  mounted() {
    this.$nextTick(() => {
      //初始化页面数据
      this.initData()
    })
  },
  // beforeUpdate() {
  //   console.log("bupdate");
  // },
  // updated() {
  //   console.log("update");
  // },
  beforeDestroy() {
    if (this.singleWaitTime) clearTimeout(this.singleWaitTime)
      this.clearAnimation()
  },
  created() { },
  beforeCreate() { }
}
</script>
