index.vue 5.08 KB
<template>
  <div @mouseenter="handleMouseenter" @mouseleave="handleMouseleave" class="banner-box" ref="root">
    <div class="wrapper">
      <div v-for="(item, index) in option.dataset" :key="index" :class="item.className" :style="item.sty">
        <VideoPlayer :key="item + index" :dataset="item" :width="w" :height="h"/>
      </div>
    </div>
    <a v-show="isShowSvg" href="javascript:;" class="left" @click="changeSlide('left')"></a>
    <a v-show="isShowSvg" href="javascript:;" class="right" @click="changeSlide('right')"></a>
  </div>
</template>
<script setup lang="ts" name="index">
import {PropType, watch, toRefs, shallowReactive, onMounted, ref} from 'vue'
import {CreateComponentType} from '@/packages/index.d'
import {option as typeOption} from './config'
import VideoPlayer from "@/packages/components/external/Informations/Mores/Camera/components/VideoPlayer.vue";

const props = defineProps({
  chartConfig: {
    type: Object as PropType<CreateComponentType>,
    required: true
  }
})

const isShowSvg = ref(false)

const {w, h} = toRefs(props.chartConfig.attr)

const {autoSwitch, interval} = toRefs(props.chartConfig.option)

//暂定 any类型
const option = shallowReactive<{ ['dataset']: any }>({
  dataset: typeOption.dataset
})

let initial = ref(0)

const computedFunc = (initial: number, source: Recordable[]) => {
  if (initial < 0) initial = 0
  if (Array.isArray(source)) {
    let len = source.length,
        temp1 = initial - 2 < 0 ? initial - 2 + len : initial - 2,
        temp2 = initial - 1 < 0 ? initial - 1 + len : initial - 1,
        temp3 = initial,
        temp4 = initial + 1 >= len ? initial + 1 - len : initial + 1,
        temp5 = initial + 2 >= len ? initial + 2 - len : initial + 2
    return source?.map((item: Recordable, index: number) => {
      let transform = `translateX(-50%) scale(0.7)`,
          zIndex = 0,
          className = 'slide'
      switch (index) {
        case temp3:
          transform = `translateX(-50%) scale(1)`
          className = ['slide', 'activate'] as string[] & string
          zIndex = 300
          break
        case temp1:
          transform = `translateX(-80%) scale(0.7)`
          zIndex = 100
          break
        case temp5:
          transform = `translateX(100%) scale(0.7)`
          zIndex = 100
          break
        case temp2:
          transform = `translateX(-100%) scale(0.85)`
          zIndex = 200
          break
        case temp4:
          transform = `translateX(58%) scale(0.85)`
          zIndex = 200
          break
      }
      item.sty = {
        transform,
        zIndex
      }
      item.className = className
      return item
    })
  }
}

watch(
    () => props.chartConfig.option.dataset,
    newData => {
      option.dataset = newData
    },
    {
      immediate: true,
      deep: true
    }
)

option.dataset = computedFunc(initial.value, option.dataset)

watch(
    () => initial.value,
    newV => {
      option.dataset = computedFunc(newV, option.dataset)
    }
)

// 处理自动轮播
// 暂定 any类型
let timer: any = null

const autoPlay = () => {
  timer = setInterval(() => {
    initial.value++
    if (initial.value >= option.dataset.length) {
      initial.value = 0
    }
  }, interval.value)
}

// 鼠标移入移除效果
let root = ref<HTMLElement>()

onMounted(() => {
  clearInterval(timer)
  root.value!.onmouseenter = () => clearInterval(timer)
  if (autoSwitch.value) {
    autoPlay()
    root.value!.onmouseleave = () => autoPlay()
  }
})

// 点击左右按钮切换图片
function changeVideo(dir: string) {
  if (dir === 'left') {
    clearInterval(timer)
    initial.value++
    initial.value >= option.dataset.length ? (initial.value = 0) : false
    return
  }
  initial.value--
  initial.value < 0 ? (initial.value = option.dataset.length - 1) : false
}

// 左右切换图片设置防抖效果
function changeSlide(dir: string) {
  changeVideo(dir)
}

watch(
    () => autoSwitch.value,
    (newV: boolean) => {
      if (newV) {
        autoPlay()
      } else {
        clearInterval(timer)
      }
    },
    {
      immediate: true
    }
)

const handleMouseenter = () => {
  isShowSvg.value = true
}

const handleMouseleave = () => (isShowSvg.value = false)
</script>

<style lang="scss" scoped>
.banner-box {
  .wrapper {
    height: 100%;
    display: flex;
    overflow: hidden;

    .slide {
      width: 20%;
      height: 100%;
      position: absolute;
      left: 10%;
      transform: translateX(-50%);
      transition: 0.5s;
      // box-shadow: 0 0 4px black;
      .video-title {
        width: v-bind('w+"px"');
        font-size: 30px;
        color: white;
        position: absolute;
        bottom: 6%;
        left: 10%;
        z-index: 999;
      }
    }
  }

  .arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 90000000;
    width: 50px;
    height: 50px;
    background-size: contain;
    background-color: white;
    opacity: 0.5;
  }

  a.left {
    @extend .arrow;
    background-image: url('./static/left.svg');
    left: 0px;
  }

  a.right {
    @extend .arrow;
    background-image: url('./static/right.svg');
    right: 0px;
  }
}
</style>