vue视频、图片自动轮播并伴随进度条

废话不多说直接上代

多余没用的部分自己看着删除

javascript 复制代码
<template>
  <div class="showImg">
    <el-carousel ref="carousel" trigger="hover" :autoplay="false" class="dimControl" :height="`${(currenInnerWith*0.375) > 3840 ? 1440 : currenInnerWith*0.375}px`"
                 @change="carouselChange" :interval="5000" arrow="never" style="cursor: pointer;">
      <el-carousel-item v-for="(item,index) in imgArr" :key="item.id">

        <!-- @timeupdate="commonVideoUpdata(index,'video')" -->
        <template v-if="item.banner_type==2 && isIndex==index">
          <video
            :ref="'videoRef'+index"
            @click="gotoBanner(item)"
            class="box-bg video-bg"
            :class="'videoRef'+index"
            :id="'videoRef'+index"
            :muted="true"
            autoplay="autoplay"
            @mouseover="changeInterval(true)"
            @mouseleave="changeInterval(false)"
            :poster="item.video_cover_url"
            :src="item.video_url"/>
          <span v-if="isAudioBox" class="audio-box" @click="handleAudio(index,9)">
            <i v-if="!isIcon" class="iconfont audio-icon" @click.stop="handleAudio(index,true)">&#xe6de;</i>
            <i v-if="isIcon" class="iconfont audio-icon" @click.stop="handleAudio(index,false)">&#xe6db;</i>
          </span>


        </template>

        <div
          v-else
          @click="gotoBanner(item)"
          class="box-bg"
          @mouseover="changeInterval(true)"
          @mouseleave="changeInterval(false)"
          :style="`background-image:url(${item.url});height:${(currenInnerWith*0.375) > 3840?1440:currenInnerWith*0.375}px`"
          alt="#"
          :src="item.url"
        />
      </el-carousel-item>
    </el-carousel>
    <div class="category-list">
    </div>
  </div>
</template>

<script>
import axiosSrr from "@/plugins/ssr-axios";


export default {
  props: {
    datas: {
      type: Object
    },
    isSwiperTool: {
      type: Boolean,
      default: true
    }
  },

  async fetch(){
      return axiosSrr.post("/banner/OWI_GetBanner", {
        banner_code: "home_banner"
      }).then((res) => {
        let retData = [];
        res.data.data.entities.forEach((item, i) => {
          let arr = {};
          arr.url = item.image_url;
          arr.id = i;
          arr.display_order = Number(item.display_order);
          arr.redirect_url = item.redirect_url;

          arr.banner_type = item.banner_type;
          arr.image_url2 = item.image_url2;
          arr.image_url3 = item.image_url3;
          arr.video_cover_url = item.video_cover_url;
          arr.video_url = item.video_url;
          retData.push(arr);
        });

        this.imgArr = retData;
        this.banner_duration = res.data.data.banner_duration



      });
  },

  data() {
    return {
      currentIndex: 0, //当前所在图片下标
      timer: null, //定时轮询
      imgArr: [],
      carouselData: {
        pic: {
          // master: require("@/assets/img/bitmap.png"),
          master: [
            require("@/assets/banner-bg/banner1_4k.png"),
            require("@/assets/banner-bg/banner1_4k.png"),
            require("@/assets/banner-bg/banner1_4k.png")
          ],

          gifs: require("@/assets/img/dynamic_graph.png")
        }
      },

     
      screenWidth: 1440,
      industryData: [], //banner 下行业分类信息
      notice: '',
      currentTimeProgress: 0,
      isIndex: 0,
      intervalId: null,
      timeInterval: null,
      banner_duration: 5,
      isAudio: false,
      isIcon: false,
      isAudioBox: false,
      isCount: 0,
      currenInnerWith:1920,
      loopTimer:false,

    };
  },

 
  methods: {
    openTip() {
    },
    async getNotice() {
      let dataRet = await this.$axios.post("common_api/OWI_GetAnnouncementList")
      this.notice = dataRet.data.msg_list
    },
    /**
     * 屏幕尺寸判断
     */
    screenChange(e) {
      if(!process.browser){
        return
      }
      let width = document.body.clientWidth;
      // let width = 3840;

      let p = "";
      // p=width < 2048?e[0]:(2048 <= width && width < 3840?e[1]:e[2])
      if (width < 2048) {
        p = e[0];
      } else if (2048 <= width && width < 3840) {
        p = e[1];
      } else {
        p = e[2];
      }
      return p;
    },
    //开启定时器
    startIntervals() {
      // 事件里定时器应该先清除在设置,防止多次点击直接生成多个定时器
      clearInterval(this.timer);
      this.timer = setInterval(() => {
        this.currentIndex++;
        if (this.currentIndex > this.imgArr.length - 1) {
          this.currentIndex = 0;
        }
      }, 5000);
    },
    // 点击左右箭头
    clickIcon(val) {
      if (val === "down") {
        this.currentIndex++;
        if (this.currentIndex === this.imgArr.length) {
          this.currentIndex = 0;
        }
      } else {
        /* 第一种写法
					this.currentIndex--;
					if(this.currentIndex < 0){
						this.currentIndex = this.imgArr.length-1;
					} */
        // 第二种写法
        if (this.currentIndex === 0) {
          this.currentIndex = this.imgArr.length;
        }
        this.currentIndex--;
      }
    },
    // 点击控制圆点
    changeImg(index) {
      this.currentIndex = index;
    },
    /**
     * 鼠标移入事件
     */
    enter(e, id) {
      this.currentIndex = id;
    },
    //鼠标移入移出控制
    changeInterval(val) {
      if (val) {
        clearInterval(this.timer);

      } else {
        // this.startInterval();
      }
    },
    gotoBanner(val) {
      if (val.redirect_url) {
        window.open(val.redirect_url);
      }
    },
    getIndustryImg(val) {
      switch (val) {
        case "直播":
          return require("@/assets/img/cover_trade_ZhiBo.png");
          break;
        case "数字营销":
          return require("@/assets/img/cover_trade_ShuZiYingXiao.png");
          break;
        case "数据新闻":
          return require("@/assets/img/cover_trade_ShuJuXinWen.png");
          break;
        case "短视频":
          return require("@/assets/img/cover_trade_DuanShiPin.png");
          break;
        case "数字创意":
          return require("@/assets/img/cover_trade_ShuZiChuangYi@2x.png");
          break;
        case "数字文物":
          return require("@/assets/img/cover_trade_ShuZiWenWu@2x.png");
          break;
        case "桥梁模型":
          return require("@/assets/img/cover_trade_bridge@2x.png");
          break;
        case "数字信息":
          return require("@/assets/img/cover_trade_ShuZiXinXi.png");
          break;
      }
    },
    // 获取行业应用
    async getIndustryApplication() {
      let res = await this.$axios.post("/banner/OWI_GetBanner", {
        banner_code: "home_industry_application"
      });
      let arr=[]
      let arrSort=res.data.entities?.sort((a, b) => {
          return a.display_order - b.display_order;
        })
      arrSort?.map(item=>{
        arr.push({
          url: item.redirect_url,
          bg: item.image_url
        })
      })
      if (process.browser) {
        this.$nextTick(() => {
          this.industryData = arr
        })
      }
    },
    async getindustryData() {
      let res = await this.$axios.post("/api_source/OWI_TreeCategoryV2", {
        category_type: 10,
        current_category_show_id: "",
        only_show_categories: true
      });
      this.industryData = [];
      let industryIndex = 0;

      let mapData = new Map();


      res.data.entities.forEach(item => {

        let industryitem = item.self;
        industryitem.bg = this.getIndustryImg(industryitem.name);
        industryitem.url = `/web_site_front/resources/resources_model_new1?parentVal=行业应用&ClassName=${industryitem.name}&showId=${industryitem.show_id}`;
        industryitem.title = industryitem.name;
        mapData.set(industryitem.title, industryitem)
        //this.industryData.push(industryitem);
        //industryIndex++;
      });
      

      let freeObj = {
        name: '限时免费',
        url: 'https://www.cgpool.com/web_site_front/resourcesArea/resources_zone_info?id=300',
        bg: require('@/assets/img/cover_trade_Xianshi@2x.png')
      }

      mapData.set(freeObj.name, freeObj)

      let bridge = {
        name: '桥梁模型',
        url: 'https://www.cgpool.com/web_site_front/resourcesArea/resources_zone_info?id=290',
        bg: require('@/assets/img/cover_trade_bridge@2x.png')
      }

      mapData.set(bridge.name, bridge)

      let digiDecoration = {
        name: '数字家装',
        url: 'https://www.cgpool.com/web_site_front/resourcesArea/resources_zone_info?id=301',
        bg: require('@/assets/img/cover_trade_jiazhuang@2x.png')
      }

      mapData.set(digiDecoration.name, digiDecoration)


      let intelligentManufacture = {
        name: '智能制造',
        url: 'https://www.cgpool.com/web_site_front/resourcesArea/resources_zone_info?id=209',
        bg: require('@/assets/img/cover_trade_zhizao@2x.png')
      }

      mapData.set(intelligentManufacture.name, intelligentManufacture)


      let BAndB = {
        name: '民宿模型',
        url: 'https://www.cgpool.com/web_site_front/resourcesArea/resources_zone_info?id=292',
        bg: require('@/assets/img/cover_trade_minsu@2x.png')
      }

      mapData.set(BAndB.name, BAndB)

      // 2024 0408 需求更改
      // 1 限时免费 2 数字创意  3 数字家装 4 智能制造  5 桥梁模型 6 短视频
      let tmpArray = [];
      let Index1 = mapData.get("限时免费")
      tmpArray.push(Index1)
      let Index2 = mapData.get("数字创意")
      tmpArray.push(Index2)
      let Index3 = mapData.get("数字家装")
      tmpArray.push(Index3)
      let Index4 = mapData.get("智能制造")
      tmpArray.push(Index4)
      let Index5 = mapData.get("桥梁模型")
      tmpArray.push(Index5)
      let Index6 = mapData.get("民宿模型")
      tmpArray.push(Index6)
      // this.industryData = tmpArray

      // this.industryData.splice(1,1)
      // this.industryData.splice(2,0,sliceArr[0])

      /**
       *
       */
    },
    async getBanner() {
      let res = await this.$axios.post("/banner/OWI_GetBanner", {
        banner_code: "home_banner"
      });
      this.banner_duration = res.data.banner_duration;
      this.imgArr=[]
      res.data.entities.forEach((item, i) => {
        let arr = {};
        arr.url = item.image_url;
        arr.id = i;
        arr.display_order = Number(item.display_order);
        arr.redirect_url = item.redirect_url;

        arr.banner_type = item.banner_type;
        arr.image_url2 = item.image_url2;
        arr.image_url3 = item.image_url3;
        arr.video_cover_url = item.video_cover_url;
        arr.video_url = item.video_url;
        this.imgArr.push(arr);
      });
      if (this.imgArr.length > 0) {
        this.createElChange()
        this.carouselChange(0)
      }

    },
    // 公共video获取时间
    commonVideoUpdata(id, type) {
      const self = this
      if(!process.browser){
        return
      }
      let videoEl = document.getElementsByClassName('videoRef' + id)


      videoEl[0]?.addEventListener("timeupdate", function () {
        let el = document.querySelector(".new-indicator")
        if (el) {
          let currTime = this.currentTime //当前时间
          let duration = this.duration //总时间
          let pre = currTime / duration
          self.setStyleHandel(pre * 40)
          if (this.currentTime == this.duration) {
            self.handelNext()
            return
          }
        }
      })

    },
    handleToggleImg() {
      const self = this
      let time = self.banner_duration * 1000
      let times = self.banner_duration * 1000 + 300
      clearInterval(self.intervalId);
      if(!process.browser){
        return
      }
      let el = document.querySelector(".new-indicator")
      if (el) {
        let count = 0; // 计数器
        // let intervalId; // 用于保存 setInterval 返回的 ID
        function executeTask() {
          // 执行任务的逻辑,这里假设是打印当前计数
          count++; // 增加计数
          self.setStyleHandel((40 / (time / 100)) * count)
          if (count === time / 100) {
            // 达到执行次数上限,停止定时器
            clearInterval(self.intervalId);
          }
        }

        // 每200毫秒执行一次 executeTask 函数
        self.intervalId = setInterval(executeTask, 100);
        // 5秒后停止定时器
        clearInterval(self.timeInterval);
        self.timeInterval = setInterval(() => {
          clearInterval(self.intervalId);
          clearInterval(self.timeInterval);
          self.handelNext()
        }, times);
      }
    },

    setStyleHandel(count) {
      if(!process.browser){
        return
      }
      let el = document.querySelector(".new-indicator")
      el.style.opacity = 1
      el.style = "background: #fff"
      el.style.width = `${count >= 6 ? count : 6}px`
    },
    carouselChange(e) {
      if (process.browser) {
        this.isIndex = e
        this.isAudioBox = true
        this.isAudio = false
        this.isIcon = false
        this.isCount = 0
        clearInterval(this.intervalId);
        clearInterval(this.timeInterval);
        if (process.browser) {
          this.$nextTick(() => {

            this.handleSetLeft()

            let el = document.querySelectorAll(".new-indicator")
            el?.forEach(function (indicator) {
              indicator.style = "width:6px"
              indicator.style = "opacity:0"
              indicator.style = "background: rgba(255, 255, 255, 0.45)"
            });
            this.imgArr?.map((item, i) => {
              let videoObj = this.$refs['videoRef' + i]

              if (Object(videoObj).length > 0) {
                videoObj[0].currentTime = 0
                setTimeout(() => {
                  videoObj[0].play()
                }, 500);


                // let playTimer=setTimeout(() => {
                //   // videoObj[0].muted=false
                //   videoObj[0].play()
                // },500);
                // clearTimeout(playTimer);
              }

            })
            this.createElChange()
            if (Object(this.imgArr).length > 0) {
              el.forEach(item => {
                item.style = `width:${0}%`
              })
            }
            if (this.imgArr[e].banner_type == 1) {
              this.handleToggleImg()
            } else {
              this.commonVideoUpdata(e, 'video')
            }
          })
        }
      }
    },
    handleAudio(id, Boolean) {
      const self = this
      self.isCount++
      // 获取 video 元素
      const myVideo = self.$refs['videoRef' + id];
      // 切换静音状态
      self.isAudio = !self.isAudio;
      // 更新视频静音状态
      myVideo[0].muted = self.isAudio;
      self.isIcon = !self.isAudio
      // 如果是第一次点击,并且视频正在播放,触发播放
      if (!self.isAudio && !myVideo[0].paused) {
        myVideo[0].play();
      }

      if (self.isCount == 1) {
        this.handleAudio(id, Boolean)
      }
    },

    handelNext() {
      if (process.server){
        return
      }
      this.isAudioBox = false;
      if (this.imgArr?.length == 1 && this.imgArr[this.isIndex]?.banner_type == 2) {
        this.isCount++;
        this.isIcon = true
        this.isAudioBox = true;
        // 获取 video 元素
        const myVideo = this.$refs["videoRef" + this.isIndex];
        myVideo?.forEach((item, i) => {
          item.muted = true
        })
      }
      this.$refs.carousel?.next();
      if (this.imgArr.length == 1) {
        this.carouselChange(0);
      }
    },
    createElChange() {
      if (process.browser) {
        this.$nextTick(() => {
          let indicators = document.querySelectorAll(".new-indicator")
          // 删除这些元素
          indicators.forEach(function (indicator) {
            indicator.parentNode.removeChild(indicator);
          });
          const indicatorElement = this.$refs.carousel.$el.querySelector('.el-carousel__indicator.is-active');
          const newElement = document.createElement('span');
          newElement.textContent = '';
          newElement.className = 'new-indicator';
          newElement.style.width = `6px`;
          newElement.style.opacity = `0`;
          indicatorElement?.appendChild(newElement);
        })
      }
    },
    handleSetLeft() {
      if (process.browser) {
        this.$nextTick(() => {
          let element = document.querySelector(".showImg .el-carousel__indicators")
          let audio = document.querySelector(".showImg .audio-box")
          let leftDistance = element.getBoundingClientRect().left;
          // 输出距离
          if (audio) {
            audio.style = `left:${leftDistance + window.pageXOffset + element.clientWidth + 12}px`
          }
        })
      }


    },
    gotoIndustryInfo(val) {
      window.open(val.url);
    }
  },
  //进入页面后启动定时轮询
  mounted() {
    // this.getindustryData();
    this.getIndustryApplication();
    this.getBanner();
    this.startIntervals();
    this.startIntervals();
    this.getNotice();
    const self = this
    window.addEventListener("resize", function () {
      self.handleSetLeft()

      if (!self.loopTimer) { // 使用节流机制,降低函数被触发的频率
        self.loopTimer = true;
        setTimeout(function () {
          window.screenWidth = window.innerWidth;
          self.loopTimer = false;
          self.$nextTick(() => {
            if(window.screenWidth>3840){
              self.currenInnerWith = 3840

            }else{
              self.currenInnerWith = window.screenWidth;

            }
          })

        }, 100)
      }
    });
    if(window.innerWidth>3840){
      this.currenInnerWith = 3840
    }else{
      this.currenInnerWith = window.innerWidth;
    }
  },
  destroyed() {
    // 组件销毁后解绑事件
    window.onresize = null;
  },
};
</script>

<style lang="scss" scoped>
$desktop2: "only screen and (max-width: 1295px)";
$desktop: "only screen and (min-width: 1296px)";
$desktop1500: "only screen and (min-width: 1500px)";
$desktop1501: "only screen and (min-width: 1501px) and (max-width: 1799px)";
$desktop1800: "only screen and (min-width: 1800px)";
$desktop_3840: "only screen and (min-width: 3840px)";
$desktop_4000: "only screen and (min-width: 4000px)";
.fontText {
  @media #{$desktop} {
    margin: 0 72px;
  }
  @media #{$desktop1500} {
    margin: 0 56px;
  }
  @media #{$desktop1501} {
    margin: 0 72px;
  }
  @media #{$desktop1800} {
    margin: 0 72px;
  }
  @media #{$desktop2} {
    margin: 0 72px;
  }
  @media #{$desktop_3840} {
    margin: 0px auto;
  }
  @media #{$desktop_4000} {
    margin: 0px auto;
  }
  margin: 0px;
}

* {
  padding: 0;
  margin: 0;
}

/* 清除li前面的圆点 */
li {
  list-style-type: none;
}

.showImg {
  position: relative;
  width: 100%;
  // height: 587px;
  background: #fafafa;

  .box-category {
    // position: absolute;
    // top: calc(100% - 48px);
    // right: calc((100% - 1440px) / 2 - -220px);
    transform: translateY(-50%);
    width: 64px;
    height: 30px;
    border-radius: 15px;
    background-color: rgba(25, 27, 41, 0.45);
    line-height: 30px;
    text-align: center;
    font-size: 25px;
    cursor: pointer;
    color: rgba(255, 255, 255, 0.45);
    margin-right: 8px;
    margin-top: 14px;

    i {
      font-weight: bold;
    }
  }

  .box-bg {
    // height: 585px;
    width: 100%;
    height: 100%;
    max-width: 3840px;
    max-height: 1440px;
    background-repeat: no-repeat;
    margin: 0 auto;

    background-size: cover;
    background-repeat: no-repeat;
    background-position: center center;

    .img-box {
      width: 365px;
      position: absolute;
      left: calc((100% - 1440px) - -15px);
      z-index: 2;

      img {
        max-width: 100%;
        margin-top: 290px;
      }
    }
  }

  .video-bg {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .audio-box {
    border-radius: 50%;
    background-color: #00000073;
    height: 40px;
    width: 40px;
    position: absolute;
    bottom: 26px;
    text-align: center;
    line-height: 40px;

    &:hover {
      background-color: rgba(255, 255, 255, 0.25);
    }

    .audio-icon {
      cursor: pointer;
      color: #fff;
    }
  }

}

/* 轮播图片 */
.showImg img {
  width: 100%;
  height: 100%;
}

/* 箭头图标 */
.iconDiv {
  display: inline-block;
}

.iconDiv:hover {
  color: #fff;
}

/* 控制圆点 */
.banner-box {
  position: absolute;
  right: calc((100% - 1440px) / 2 - -70px);
  top: calc(100% - 63px);
  display: flex;
}

.banner-circle {
  height: 20px;

  background-color: rgba(25, 27, 41, 0.45);
  border-radius: 15px;
  line-height: 30px;
  height: 30px;
}

.banner-circle ul {
  margin: 0 20px;
  height: 100%;
  display: flex;
}

.banner-circle ul li {
  display: inline-block;
  width: 14px;
  height: 14px;
  margin: 0 5px;
  border-radius: 7px;
  background-color: rgba(255, 255, 255, 0.3);
  cursor: pointer;
  align-self: center;
}

.active {
  background-color: #ffffff !important;
  width: 30px !important;
  border-radius: 7px !important;
}

@keyframes hoverLi {
  0% {
    width: 14px;
  }
  25% {
    width: 20px;
  }
  50% {
    width: 24px;
  }
  75% {
    width: 28px;
  }
  100% {
    width: 30px;
  }
}

.active:hover {
  animation-name: hoverLi;
  animation-duration: 3s;
}

.category-list {
  margin: 0 auto;
  align-self: center;
}

::v-deep .el-carousel {
  width: 100vw;
}

::v-deep .el-carousel__item {
  width: 100%;
}

::v-deep .el-carousel__indicators {
  height: 40px;
  padding: 0 28px;
  background: rgba(0, 0, 0, 0.45);
  border-radius: 20px;
  bottom: 26px;
  // left: 75%;

  .el-carousel__indicator {
    line-height: 40px;
    height: 40px;
    margin-top: 0px;
  }

  .el-carousel__indicator--horizontal {
    padding: 12px 0;
    margin: 0 4px;
  }

  .is-active {
    max-width: 40px;
    position: relative;

    .new-indicator {
      width: 6px;
      height: 8px;
      position: absolute;
      top: 15px;
      border-radius: 6px;
      transition: width .3s;
    }

    .el-carousel__button {
      width: 40px;
      height: 8px;
      border-radius: 6px;
      background: rgba(255, 255, 255, 0.45);

    }
  }

  .el-carousel__button {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.45);
    margin-top: 3px;
  }
}

.category-list {
  .fontText {
    display: flex;
    justify-content: space-between;
    // margin:0 72px;
    margin-top: 40px;
    min-width: 1296px;
    max-width: 3678px;
    font-family: Alibaba-PuHuiTi-B;

    .hangyeImgSty {
      width: 40px;
      height: 40px;
      position: relative;
      top: 8px;
      margin-right: 10px;
    }

    .Notice {
      width: 426px;
      height: 56px;
      background: url("@/assets/img/NoticeBg.png") no-repeat;
      background-size: 100% 100%;
      display: flex;
      cursor: pointer;
      //  align-items: center;
      .NoticeIcon {
        width: 24px;
        height: 24px;
        margin: 16px 12px 16px 24px;

      }

      span {
        line-height: 52px;
        height: 56px;
      }
    }
  }

}

</style>
相关推荐
Devil枫5 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
hairenjing11236 小时前
使用 Mac 数据恢复从 iPhoto 图库中恢复照片
windows·stm32·嵌入式硬件·macos·word
GIS程序媛—椰子6 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
毕业设计制作和分享7 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
程序媛小果7 小时前
基于java+SpringBoot+Vue的旅游管理系统设计与实现
java·vue.js·spring boot
从兄8 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
九鼎科技-Leo8 小时前
了解 .NET 运行时与 .NET 框架:基础概念与相互关系
windows·c#·.net
凉辰8 小时前
设计模式 策略模式 场景Vue (技术提升)
vue.js·设计模式·策略模式
我喜欢就喜欢10 小时前
基于qt vs下的视频播放
开发语言·qt·音视频
薛一半10 小时前
PC端查看历史消息,鼠标向上滚动加载数据时页面停留在上次查看的位置
前端·javascript·vue.js