<template>
  <div
    ref="scrollBox"
    :class="`infinite-scroll-component-box-${direction}`"
    :style="{
      '--speed-': `${speed}s`,
      mask: `linear-gradient(${degList[direction]}, #000 70%, transparent)`
    }"
  >
    <div class="scroll-content" ref="scrollContent">
      <template v-if="Array.isArray(content)">
        <div v-for="(item, index) in content" :key="'arrayFirst' + index" class="loop-item">
          <slot :item="item" :index="index"></slot>
        </div>
        <template v-if="loop">
          <div v-for="(item, index) in content" class="loop-item" :key="'arrayCopy' + index">
            <slot :item="item" :index="index"></slot>
          </div>
        </template>
      </template>
      <template v-else>
        <slot></slot>
        <slot v-if="loop"></slot>
      </template>
    </div>
  </div>
</template>

<script setup>
  const props = defineProps({
    direction: {
      type: String,
      default: 'top',
      validate: (value) => ['left', 'top', 'right', 'bottom'].findIndex(value) !== -1
    },

    content: {
      type: [String, Array],
      default: ''
    },

    mask: {
      type: Boolean,
      default: true
    },

    // 速率倍速，越大越快，默认值20
    speedRate: {
      type: Number,
      default: 20
    }
  })

  onMounted(() => {
    init()
  })

  let degList = {
    left: '90deg',
    top: '180deg',
    right: '270deg',
    bottom: '0deg'
  }
  // 滚动速度
  let speed = ref(0)
  // 是否需要无限滚动
  let loop = ref(false)
  // 容器ref
  let scrollBox = ref()

  watch(
    () => props.content,
    () => {
      loop.value = false
      init()
    },
    { deep: true }
  )

  // 初始化速度，以及是否需要无限滚动
  const init = async () => {
    await nextTick()
    if (props.direction === 'left' || props.direction === 'right') {
      // 可视区域的宽度
      const boxWidth = scrollBox.value.offsetWidth
      // 滚动内容的宽度
      const itemWidth = scrollBox.value.getElementsByClassName('scroll-content')[0].offsetWidth
      if (itemWidth >= boxWidth) {
        loop.value = true
        speed.value = itemWidth / props.speedRate
      } else {
        speed.value = 0
        scrollBox.value.getElementsByClassName('scroll-content')[0].style.transform =
          'translateX(0)'
        loop.value = false
      }
    } else {
      const boxHeight = scrollBox.value.offsetHeight
      const itemHeight = scrollBox.value.getElementsByClassName('scroll-content')[0].offsetHeight
      if (itemHeight >= boxHeight) {
        loop.value = true
        speed.value = itemHeight / props.speedRate
      } else {
        speed.value = 0
        scrollBox.value.getElementsByClassName('scroll-content')[0].style.transform =
          'translateY(0)'
        loop.value = false
      }
    }
  }
</script>

<style lang="scss" scoped>
  .infinite-scroll-component-box-left,
  .infinite-scroll-component-box-right {
    width: 100%;
    height: 100%;
    overflow: hidden;
    position: relative;

    .scroll-content {
      position: absolute;
      left: 0;
      display: flex;
      align-items: center;
      justify-content: center;

      &:hover {
        animation-play-state: paused;
      }
    }
  }
  .infinite-scroll-component-box-top,
  .infinite-scroll-component-box-bottom {
    width: 100%;
    height: 100%;
    overflow: hidden;
    position: relative;

    .scroll-content {
      width: 100%;
      position: absolute;
      left: 0;
      display: flex;
      align-items: center;
      justify-content: center;

      &:hover {
        animation-play-state: paused;
      }

      .loop-item {
        width: 100%;
      }
    }
  }
  .infinite-scroll-component-box-left .scroll-content {
    flex-direction: row;
    animation: var(--speed-) move-left linear infinite;

    @keyframes move-left {
      0% {
        transform: translateX(0);
      }
      100% {
        transform: translateX(-50%);
      }
    }
  }

  .infinite-scroll-component-box-right .scroll-content {
    flex-direction: row-reverse;
    animation: var(--speed-) move-right linear infinite;

    @keyframes move-right {
      0% {
        transform: translateX(-50%);
      }
      100% {
        transform: translateX(0);
      }
    }
  }

  .infinite-scroll-component-box-top .scroll-content {
    flex-direction: column;
    animation: var(--speed-) move-top linear infinite;

    @keyframes move-top {
      0% {
        transform: translateY(0);
      }
      100% {
        transform: translateY(-50%);
      }
    }
  }

  .infinite-scroll-component-box-bottom .scroll-content {
    flex-direction: column-reverse;
    animation: var(--speed-) move-bottom linear infinite;

    @keyframes move-bottom {
      0% {
        transform: translateY(-50%);
      }
      100% {
        transform: translateY(0);
      }
    }
  }
</style>
