index.vue 4.45 KB
<template>
  <div class="banner-box" ref="root">
    <div class="wrapper">
      <div v-for="(item, index) in option.dataset" :key="index + item" :class="item.className" :style="item.sty">
        <CameraItem ref="cameraRef" :key="item + index" :sourceSrc="item.url" :w="w" :h="h" :index="index" />
      </div>
    </div>
    <a href="javascript:;" class="left" @click="changeSlide('left')"></a>
    <a href="javascript:;" class="right" @click="changeSlide('right')"></a>
  </div>
</template>
<script setup lang="ts">
import { PropType, watch, toRefs, shallowReactive, onMounted, ref } from 'vue'
import { CreateComponentType } from '@/packages/index.d'
import 'video.js/dist/video-js.min.css'
import { option as configOption } from './config'
import CameraItem from './cameraItem.vue'

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

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

const option = shallowReactive({
  dataset: configOption.dataset
})

const cameraRef = ref<InstanceType<typeof CameraItem>>()

let initial = ref(0)

let interval = ref(4000)

const computedFunc = (initial: number, source: any) => {
  if (initial < 0) initial = 0
  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: any, index: number) => {
    let transform = `translate(-50%, -50%) scale(0.7)`,
      zIndex = 0,
      className = 'slide'
    switch (index) {
      case temp3:
        transform = `translate(-50%, -50%) scale(1)`
        className = ['slide', 'activate'] as any
        zIndex = 3
        break
      case temp1:
        transform = `translate(-80%, -50%) scale(0.7)`
        zIndex = 1
        break
      case temp5:
        transform = `translate(100%, -50%) scale(0.7)`
        zIndex = 1
        break
      case temp2:
        transform = `translate(-100%, -50%) scale(0.85)`
        zIndex = 2
        break
      case temp4:
        transform = `translate(58%, -50%) scale(0.85)`
        zIndex = 2
        break
    }
    item.sty = {
      transform,
      zIndex
    }
    item.className = className
    return item
  })
}

watch(
  () => props.chartConfig.option.dataset,
  newData => {
    option.dataset = newData
    console.log(option.dataset)
  },
  {
    immediate: true,
    deep: true
  }
)
option.dataset = computedFunc(initial.value, option.dataset)

watch(
  () => initial.value,
  newV => {
    option.dataset = computedFunc(newV, option.dataset)
  }
)
// 处理自动轮播
let timer: any = null

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

// 鼠标移入移除效果
let root = ref(null)

onMounted(() => {
  clearInterval(timer)
  autoPlay()
  const box: any = root.value
  box.onmouseenter = () => clearInterval(timer)
  box.onmouseleave = () => autoPlay()
})

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

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

<style lang="scss" scoped>
.banner-box {
  width: 100%;
  height: 100%;
  // position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  .wrapper {
    width: 100%;
    height: 100%;
    position: relative;
    .slide {
      width: 20%;
      height: 100%;
      position: absolute;
      top: 50%;
      left: 10%;
      transform: translate(-50%, -50%);
      transition: 0.5s;
      box-shadow: 0 0 4px black;
    }
  }
  .arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 9;
    width: 50px;
    height: 50px;
    background-size: contain;
    background-color: white;
    opacity: 0.5;
  }
  a.left {
    @extend .arrow;
    background-image: url(./left.svg);
    left: 0px;
  }
  a.right {
    @extend .arrow;
    background-image: url(./right.svg);
    right: 0px;
  }
}
</style>