IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Vue走马灯(扩展版) -> 正文阅读

[JavaScript知识库]Vue走马灯(扩展版)

效果如下图:(Vue走马灯的扩展版)

Vue走马灯_theMuseCatcher的博客-CSDN博客_vue滚动图片

可自定义设置

  • 走马灯图片宽度
  • 图片高度
  • 滑动轮播时间间隔
  • 轮播图片数组

主要具有以下功能:

  • 根据设置的时间间隔自动定时滚动切换图片
  • 鼠标移入组件内部时,暂停切换,移出后自动开始切换图片
  • 页面未激活时会自动暂停切换,待激活时自动开始切换图片
  • 鼠标移入组件内部时,点击左右箭头可以手动切换到上一张,下一张图片
  • 根据传入图片数组展示相应数量的底部图片标识,并显示当前是第几张,同时点击可以直接切换到指定图片

该组件的所有滑动效果均采用的setInterval延时调用模拟,如果换成requestAnimationFrame()实现一样可行,具体实现可参考Vue简单走马灯_theMuseCatcher的博客-CSDN博客_vue滚动图片

①创建ImageSlider.vue组件:

<template>
  <div class="m-slider" :style="`width: ${imageWidth}px;`" @mouseover="onStop" @mouseleave="onStart">
    <div :class="{'transition': transition}" :style="`width: ${width}px; will-change: transform; transform: translateX(${-left}px);`">
      <div
        v-for="(item, index) in imageData"
        :key="index"
        :style="`width: ${imageWidth}px;`"
        class="m-image">
        <img v-lazy="getDefault(item && item.imgUrl)" :key="item && item.imgUrl" :alt="item && item.title" :style="`width: ${imageWidth}px; height: ${imageHeight}px;`" class="u-img"/>
        <div class="m-title" :title="item && item.title">
          <p class="u-title">{{ item && item.title || '--' }}</p>
          <p class="u-date">2022/07/12</p>
        </div>
      </div>
      <div class="m-image" :style="`width: ${imageWidth}px;`">
        <img v-lazy="getDefault(imageData[0] && imageData[0].imgUrl)" :key="imageData[0] && imageData[0].imgUrl" :alt="imageData[0]&&imageData[0].title" :style="`width: ${imageWidth}px; height: ${imageHeight}px;`" class="u-img"/>
        <div class="m-title" :title="imageData[0]&&imageData[0].title">
          <p class="u-title">{{ imageData[0] && imageData[0].title || '--' }}</p>
          <p class="u-date">2022/07/12</p>
        </div>
      </div>
    </div>
    <img src="@/assets/images/left-1.png" class="arrow-left" v-show="!leftActArrow" @mouseenter="leftActArrow=true" @mouseleave="leftActArrow=false" />
    <img src="@/assets/images/left-2.png" class="arrow-left" @click="goRight((activeSwitcher+1)%len*imageWidth)" v-show="leftActArrow" @mouseenter="leftActArrow=true" @mouseleave="leftActArrow=false" />
    <img src="@/assets/images/right-1.png" class="arrow-right" v-show="!rightActArrow" @mouseenter="rightActArrow=true" @mouseleave="rightActArrow=false"/>
    <img src="@/assets/images/right-2.png" class="arrow-right" @click="goLeft(activeSwitcher%(len+1)*imageWidth)" v-show="rightActArrow" @mouseenter="rightActArrow=true" @mouseleave="rightActArrow=false"/>
    <div class="m-switch">
      <div
        @click="onSwitch(n)"
        :class="['u-rect', {'active': activeSwitcher === n }]"
        v-for="n in len"
        :key="n">
      </div>
    </div>
  </div>
</template>
<script>
import Vue from 'vue'
import VueLazyLoad from 'vue-lazyload'
Vue.use(VueLazyLoad) // 图片懒加载插件
export default {
  name: 'ImageSlider',
  props: {
    imageData: { // 轮播图片数组
      type: Array,
      default: () => {
        return []
      }
    },
    interval: { // 自动滑动轮播间隔
      type: Number,
      default: 3000
    },
    imageWidth: { // 图片宽度
      type: Number,
      default: 400
    },
    imageHeight: { // 图片高度
      type: Number,
      default: 300
    }
  },
  data () {
    return {
      leftActArrow: false, // 左箭头激活标志
      toLeft: true, // 左滑标志,默认左滑
      rightActArrow: false, // 右箭头激活标志
      left: 0, // 滑动偏移值
      transition: false, // 暂停时为完成滑动的过渡标志
      slideTimer: null, // 轮播切换定时器
      moveTimer: null, // 向左滑动效果定时器
      autoTimer: null, // 首次自动滑动定时器
      switch: false // 是否在进行跳转切换,用于区别箭头或自动切换(false)和跳转切换(true)
    }
  },
  computed: {
    width () { // 容器宽度:(图片数组长度+1) * 图片宽度
      return (this.imageData.length + 1) * this.imageWidth
    },
    len () { // 数组长度
      return this.imageData.length || 0
    },
    activeSwitcher () { // 当前展示图片标志
      return (this.toLeft ? Math.ceil(this.left / this.imageWidth) % this.len : Math.floor(this.left / this.imageWidth) % this.len) + 1
    }
  },
  mounted () {
    window.onfocus = () => { // 页面激活状态
      this.onStart()
    }
    window.onblur = () => { // 页面未激活状态
      this.onStop()
    }
    this.onStart()
  },
  methods: {
    getDefault (src) { // 获取懒加载默认图
      return {
        src: src,
        error: require('../assets/images/defaultNews.png'),
        loading: require('../assets/images/defaultNews.png')
      }
    },
    onSwitch (n) { // 切换图片
      if (n < this.activeSwitcher) { // 往右滑动
        this.switch = true // 跳转切换标志
        const target = (n - 1) * this.imageWidth
        this.goRight(target)
      }
      if (n > this.activeSwitcher) { // 往左滑动
        this.switch = true // 跳转切换标志
        const target = (n - 1) * this.imageWidth
        this.goLeft(target)
      }
    },
    onStart () {
      if (this.len > 1) { // 超过一条时滑动
        this.toLeft = true // 重置左滑标志
        this.transition = false
        this.onAutoSlide() // 自动滑动轮播
        console.log('imageSlider start')
      }
    },
    onStop () {
      clearTimeout(this.autoTimer)
      clearTimeout(this.slideTimer)
      this.autoTimer = null
      this.slideTimer = null
      if (this.toLeft) { // 左滑箭头移出时
        this.onStopLeft()
      } else {
        this.onStopRight()
      }
      console.log('imageSlider stop')
    },
    onStopLeft () { // 停止往左滑动
      clearInterval(this.moveTimer)
      this.moveTimer = null
      this.transition = true
      this.left = Math.ceil(this.left / this.imageWidth) * this.imageWidth // ceil:向上取整,floor:向下取整
    },
    onStopRight () { // 停止往右滑动
      clearInterval(this.moveTimer)
      this.moveTimer = null
      this.transition = true
      this.left = Math.floor(this.left / this.imageWidth) * this.imageWidth // ceil:向上取整,floor:向下取整
    },
    onAutoSlide () {
      this.slideTimer = setTimeout(() => {
        // 或者使用 this.activeSwitcher % (this.len + 1) * this.imageWidth
        const target = this.left % (this.len * this.imageWidth) + this.imageWidth
        this.autoMoveLeft(target)
      }, this.interval)
    },
    goLeft (target) { // 点击右箭头,往左滑动
      this.toLeft = true // 向左滑动
      this.onStopLeft()
      this.transition = false
      this.moveLeft(target)
    },
    goRight (target) { // 点击左箭头,往右滑动
      this.toLeft = false // 非向左滑动
      this.onStopRight()
      this.transition = false
      this.moveRight(target)
    },
    autoMoveLeft (target) { // 自动切换,向左滑动效果
      if (this.left === this.len * this.imageWidth) { // 最后一张时,重置left
        this.left = 0
      }
      this.moveTimer = setInterval(() => {
        if (this.left >= target) {
          clearInterval(this.moveTimer)
          this.moveTimer = null
          this.onAutoSlide() // 自动间隔切换下一张
        } else {
          var step = Math.ceil((target - this.left) / 10) // 越来越慢的滑动过程
          this.left += step
        }
      }, 25)
    },
    moveLeft (target) { // 箭头切换或跳转切换,向左滑动效果
      if (this.left === this.len * this.imageWidth) { // 最后一张时,重置left
        this.left = 0
      }
      this.moveTimer = setInterval(() => {
        if (this.left >= target) {
          clearInterval(this.moveTimer)
          this.moveTimer = null
          if (this.switch) { // 跳转切换,完成后自动滑动
            this.switch = false
            this.onStart()
          }
        } else {
          var step = Math.ceil((target - this.left) / 10) // 越来越慢的滑动过程
          this.left += step
        }
      }, 25)
    },
    moveRight (target) { // 箭头切换或跳转切换,向右滑动效果
      if (this.left === 0) { // 第一张时,重置left
        this.left = this.len * this.imageWidth
      }
      this.moveTimer = setInterval(() => {
        if (this.left <= target) {
          clearInterval(this.moveTimer)
          this.moveTimer = null
          if (this.switch) { // 跳转切换,完成后自动滑动
            this.switch = false
            this.onStart()
          }
        } else {
          var step = Math.floor((target - this.left) / 10) // 越来越慢的滑动过程
          this.left += step
        }
      }, 25)
    },
    beforeDestroy () {
      clearTimeout(this.slideTimer)
      clearInterval(this.moveTimer)
      clearInterval(this.autoTimer)
      this.slideTimer = null
      this.moveTimer = null
      this.autoTimer = null
    }
  }
}
</script>
<style lang="less" scoped>
@themeColor: #1890FF;
.m-slider {
  position: relative;
  overflow: hidden;
  .transition {
    transition: transform 0.3s ease-out;
  }
  .m-image {
    display: inline-block;
    .u-img {
      vertical-align: bottom; // 消除img标签底部的5px
      cursor: pointer;
    }
    .m-title {
      background: #F2F4F8;
      padding: 20px;
      .u-title {
        height: 54px;
        font-size: 18px;
        font-weight: 500;
        color: #333333;
        line-height: 27px;
        cursor: pointer;
        overflow: hidden;
        text-overflow: ellipsis;
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        &:hover {
          color: @themeColor;
        }
      }
      .u-date {
        margin-top: 30px;
        text-align: right;
        height: 20px;
        font-size: 14px;
        font-weight: 400;
        color: #666666;
        line-height: 20px;
      }
    }
  }
  &:hover {
    .arrow-left {
      display: inline-block;
    }
    .arrow-right {
      display: inline-block;
    }
  }
  .arrow-left {
    display: none;
    width: 24px;
    height: 44px;
    position: absolute;
    top: 151px;
    left: 10px;
    cursor: pointer;
    vertical-align: bottom;
  }
  .arrow-right {
    display: none;
    width: 24px;
    height: 44px;
    position: absolute;
    top: 151px;
    right: 10px;
    cursor: pointer;
    vertical-align: bottom;
  }
  .m-switch {
    position: absolute;
    bottom: 16px;
    left: 20px;
    .u-rect {
      display: inline-block;
      cursor: pointer;
      margin-right: 7px;
      width: 30px;
      height: 4px;
      background: #E3E3E3;
      border-radius: 1px;
      transition: background-color 0.3s;
    }
    .active {
      background: @themeColor;
    }
  }
}
</style>

②在要使用的页面引入:

<ImageSlider :imageData="imageData" :imageWidth="520" :imageHeight="346" :interval="3000" />
import ImageSlider from '@/components/ImageSlider'
components: {
	ImageSlider
}
data () {
    return {
      imageData: [
        {
          title: 'image-1,image-1,image-1,image-1,image-1,image-1,image-1,image-1,image-1',
          imgUrl: 'image src...'
        },
        {
          title: 'image-2,image-2,image-2,image-2,image-2,image-2,image-2,image-2,image-2,image-2,image-2,image-2',
          imgUrl: 'image src...'
        },
        {
          title: 'image-3,image-3,image-3,image-3,image-3,image-3,image-3,image-3,image-3',
          imgUrl: 'image src...'
        }
      ]
   }
}

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-01 15:38:21  更:2022-05-01 15:40:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 21:49:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码