Vue2走马灯(Carousel)

2023-10-19 12:10
文章标签 vue2 carousel 走马灯

本文主要是介绍Vue2走马灯(Carousel),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Vue2走马灯扩展版(Carousel)

移入时暂停,移出后自动轮播

可自定义设置以下属性:

  • 轮播图片数组(imageData),默认[]
  • 滑动轮播间隔(interval),默认3000ms
  • 图片宽度(imageWidth),默认400px
  • 图片高度(imageHeight),默认300px

共使用两种滑动效果实现方式:

  • 延时调用setInterval(setTimeout类似)
  • requestAnimationFrame()(效果更好)

效果如下图:

①创建图片轮播组件Carousel.vue:

  • 滑动效果使用setInterval延时调用(使用setTimeout超时调用类似)
<template><!-- 方法1:使用 will-change: transform; translateX(-${left}px); --><!-- <div class="m-slider" :style="`width: ${imageWidth}px;`" @mouseenter="onStop" @mouseleave="onStart"><div :class="{ 'transition': transition }" :style="`width: ${width}px; will-change: transform; transform: translateX(${-left}px);`"> --><!-- 方法2:使用position: relative;和position: absolute; left: ${-left}px; --><div class="m-slider" :style="`position: relative; width: ${imageWidth}px; height: ${imageHeight + 36}px;`" @mouseenter="onStop" @mouseleave="onStart"><div :class="{ 'transition': transition }" :style="`width: ${width}px; position: absolute; left: ${-left}px;`"><divv-for="(item, index) in imageData":key="index":style="`width: ${imageWidth}px;`"class="m-image"><img v-lazy="getDefault(item.imgUrl)" :alt="item.title" :style="`width: ${imageWidth}px; height: ${imageHeight}px;`" class="u-img"/><p class="u-img-title" :title="item.title">{{ item.title }}</p></div><div class="m-image" :style="`width: ${imageWidth}px;`"><img v-lazy="getDefault(imageData[0].imgUrl)" :alt="imageData[0].title" :style="`width: ${imageWidth}px; height: ${imageHeight}px;`" class="u-img"/><p class="u-img-title" :title="imageData[0].title">{{ imageData[0].title }}</p></div></div></div>
</template>
<script>
import Vue from 'vue'
import VueLazyLoad from 'vue-lazyload' // 图片懒加载插件使用版本v1.3.3
Vue.use(VueLazyLoad)
export default {name: 'Carousel',props: {imageData: { // 轮播图片数组type: Array,default: () => {return []}},interval: { // 滑动轮播间隔type: Number,default: 3000},imageWidth: { // 图片宽度type: Number,default: 400},imageHeight: { // 图片高度type: Number,default: 300}},data () {return {left: 0, // 滑动偏移值transition: false, // 暂停时未完成滑动的过渡标志slideTimer: null, // 自动切换定时器moveTimer: null // 向左滑动定时器}},computed: {width () { // 容器宽度:(图片数组长度+1) * 图片宽度return (this.imageData.length + 1) * this.imageWidth},len () {return this.imageData.length || 0}},mounted () {window.onfocus = () => { // 页面激活状态this.onStart()}window.onblur = () => { // 页面未激活状态this.onStop()}this.onStart()},methods: {getDefault (src) { // 获取懒加载默认图return {src: src,error: require('../assets/images/default.png'),loading: require('../assets/images/default.png')}},onStart () {if (this.len > 1) { // 超过一条时滑动this.transition = falsethis.onAutoSlide() // 自动滑动轮播console.log('imageSlider start')}},onStop () {clearTimeout(this.slideTimer)clearInterval(this.moveTimer)this.sliderTimer = nullthis.moveTimer = nullthis.transition = truethis.left = Math.ceil(this.left / this.imageWidth) * this.imageWidth // ceil:向上取整,floor:向下取整console.log('imageSlider stop')},onAutoSlide () {this.slideTimer = setTimeout(() => {const target = this.left % (this.len * this.imageWidth) + this.imageWidththis.autoMoveLeft(target)}, this.interval)},// 滑动使用setInterval延时调用autoMoveLeft (target) { // 自动切换,向左滑动效果if (this.left === this.len * this.imageWidth) { // 最后一张时,重置leftthis.left = 0}this.moveTimer = setInterval(() => {if (this.left >= target) {clearInterval(this.moveTimer)this.moveTimer = nullthis.onAutoSlide() // 自动间隔切换下一张} else {var step = Math.ceil((target - this.left) / 10) // 越来越慢的滑动过程this.left += step}}, 25)},beforeDestroy () {clearTimeout(this.slideTimer)clearInterval(this.moveTimer)this.slideTimer = nullthis.moveTimer = null}}
}
</script>
<style lang="less" scoped>
@themeColor: #1890FF;
.m-slider {margin: 0 auto;overflow: hidden;.transition {transition: transform 0.3s ease-out;}.m-image {display: inline-block;.u-img {vertical-align: bottom; // 消除img标签底部的5pxcursor: pointer;}.u-img-title {font-size: 18px;color: #333;line-height: 36px;text-align: left;cursor: pointer;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;&:hover {color: @themeColor;}}}
}
</style>

  • 滑动效果使用requestAnimationFrame()
  • <template><div class="m-slider" :style="`width: ${imageWidth}px;`" @mouseenter="onStop" @mouseleave="onStart"><div :class="{ 'transition': transition }" :style="`width: ${width}px; will-change: transform; transform: translateX(${-left}px);`"><divv-for="(item, index) in imageData":key="index":style="`width: ${imageWidth}px;`"class="m-image"><img v-lazy="getDefault(item.imgUrl)" :alt="item.title" :style="`width: ${imageWidth}px; height: ${imageHeight}px;`" class="u-img"/><p class="u-img-title" :title="item.title">{{ item.title }}</p></div><div class="m-image" :style="`width: ${imageWidth}px;`"><img v-lazy="getDefault(imageData[0].imgUrl)" :alt="imageData[0].title" :style="`width: ${imageWidth}px; height: ${imageHeight}px;`" class="u-img"/><p class="u-img-title" :title="imageData[0].title">{{ imageData[0].title }}</p></div></div></div>
    </template>
    <script>
    import Vue from 'vue'
    import VueLazyLoad from 'vue-lazyload'
    Vue.use(VueLazyLoad) // 图片懒加载插件
    export default {name: 'Carousel',props: {imageData: { // 轮播图片数组type: Array,default: () => {return []}},interval: { // 滑动轮播间隔type: Number,default: 3000},imageWidth: { // 图片宽度type: Number,default: 400},imageHeight: { // 图片高度type: Number,default: 300}},data () {return {left: 0, // 滑动偏移值transition: false, // 暂停时未完成滑动的过渡标志slideTimer: null, // 自动切换定时器moveRaf: null, // 动画回调标识target: null, // 要移动到的目标位置start: 0,end: 0,fpsRaf: null, // fps回调标识step: 15 // 默认移动参数,对应60fps}},computed: {width () { // 容器宽度:(图片数组长度+1) * 图片宽度return (this.imageData.length + 1) * this.imageWidth},len () {return this.imageData.length || 0}},mounted () {window.onfocus = () => { // 页面激活状态this.onStart()}window.onblur = () => { // 页面未激活状态this.onStop()}this.fpsRaf = requestAnimationFrame(this.getFPS) // 获取浏览器的刷新率},methods: {getDefault (src) { // 获取懒加载默认图return {src: src,error: require('../assets/images/default.png'),loading: require('../assets/images/default.png')}},getFPS (timestamp) {// 单位ms,用1000ms/两个时间的间隔≈刷新频率fps// console.log('timestamp:', timestamp)if (this.fpsRaf === 2) {this.start = timestamp}if (this.fpsRaf === 3) {this.end = timestampconst fps = Math.floor(1000 / (this.end - this.start))if (fps === 120) {this.step = 30}}this.fpsRaf = requestAnimationFrame(this.getFPS)if (this.fpsRaf > 3) {cancelAnimationFrame(this.fpsRaf)this.onStart()}},onStart () {if (this.len > 1) { // 超过一条时滑动this.transition = falsethis.onAutoSlide() // 自动滑动轮播console.log('imageSlider start')}},onStop () {clearTimeout(this.slideTimer)this.slideTimer = nullcancelAnimationFrame(this.moveRaf)this.transition = truethis.left = Math.ceil(this.left / this.imageWidth) * this.imageWidth // ceil:向上取整,floor:向下取整console.log('imageSlider stop')},onAutoSlide () {this.slideTimer = setTimeout(() => {const target = this.left % (this.len * this.imageWidth) + this.imageWidththis.autoMoveLeft(target)}, this.interval)},// 滑动效果使用requestAnimationFrameautoMoveLeft (target) { // 自动切换,向左滑动效果if (this.left === this.len * this.imageWidth) { // 最后一张时,重置leftthis.left = 0}this.target = targetthis.moveRaf = requestAnimationFrame(this.autoLeftSlideEffect)},autoLeftSlideEffect () { // 自动向左滑动效果if (this.left >= this.target) {cancelAnimationFrame(this.moveRaf)this.onAutoSlide() // 自动间隔切换下一张} else {const move = Math.ceil((this.target - this.left) / this.step)this.left += movethis.moveRaf = requestAnimationFrame(this.autoLeftSlideEffect)}},beforeDestroy () {clearTimeout(this.slideTimer)this.slideTimer = null}}
    }
    </script>
    <style lang="less" scoped>
    @themeColor: #1890FF;
    .m-slider {margin: 100px auto;overflow: hidden;.transition {transition: transform 0.3s ease-out;}.m-image {display: inline-block;.u-img {vertical-align: bottom; // 消除img标签底部的5pxcursor: pointer;}.u-img-title {font-size: 18px;color: #333;line-height: 36px;text-align: left;cursor: pointer;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;&:hover {color: @themeColor;}}}
    }
    </style>

    ②在要使用滑动轮播图片的页面引入使用:

  • <Carousel :imageData="imageData" :imageWidth="460" :imageHeight="320" :interval="3000" />
    import Carousel from '@/components/Carousel'
    components: {Carousel
    }
    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',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...'}]}
    }

这篇关于Vue2走马灯(Carousel)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/239669

相关文章

vue2 组件通信

props + emits props:用于接收父组件传递给子组件的数据。可以定义期望从父组件接收的数据结构和类型。‘子组件不可更改该数据’emits:用于定义组件可以向父组件发出的事件。这允许父组件监听子组件的事件并作出响应。(比如数据更新) props检查属性 属性名类型描述默认值typeFunction指定 prop 应该是什么类型,如 String, Number, Boolean,

vue2实践:el-table实现由用户自己控制行数的动态表格

需求 项目中需要提供一个动态表单,如图: 当我点击添加时,便添加一行;点击右边的删除时,便删除这一行。 至少要有一行数据,但是没有上限。 思路 这种每一行的数据固定,但是不定行数的,很容易想到使用el-table来实现,它可以循环读取:data所绑定的数组,来生成行数据,不同的是: 1、table里面的每一个cell,需要放置一个input来支持用户编辑。 2、最后一列放置两个b

vue2实践:第一个非正规的自定义组件-动态表单对话框

前言 vue一个很重要的概念就是组件,作为一个没有经历过前几代前端开发的我来说,不太能理解它所带来的“进步”,但是,将它与后端c++、java类比,我感觉,组件就像是这些语言中的类和对象的概念,通过封装好的组件(类),可以通过挂载的方式,非常方便的调用其提供的功能,而不必重新写一遍实现逻辑。 我们常用的element UI就是由饿了么所提供的组件库,但是在项目开发中,我们可能还需要额外地定义一

Vue2电商项目(二) Home模块的开发;(还需要补充js节流和防抖的回顾链接)

文章目录 一、Home模块拆分1. 三级联动组件TypeNav2. 其余组件 二、发送请求的准备工作1. axios的二次封装2. 统一管理接口API----跨域3. nprogress进度条 三、 vuex模块开发四、TypeNav三级联动组件开发1. 动态展示三级联动数据2. 三级联动 动态背景(1)、方式一:CSS样式(2)、方式二:JS 3. 控制二三级数据隐藏与显示--绑定styl

vue3和vue2的双向绑定原理

Vue 的双向绑定是其核心特性之一,允许数据和视图之间保持同步。在 Vue 2 和 Vue 3 中,双向绑定的实现原理有所不同。以下是两者的原理对比: Vue 2 的双向绑定原理 在 Vue 2 中,双向绑定是通过以下机制实现的: 响应式系统: Vue 2 使用 Object.defineProperty 来实现响应式数据。通过在对象的每个属性上定义 getter 和 setter,Vue

vue2+ueditor集成秀米编辑器

一、百度富文本编辑器 1.首先下载 百度富文本编辑器    下载地址:GitHub - fex-team/ueditor: rich text 富文本编辑器 2.把下载好的文件整理好  放在图片目录下 3. 安装插件vue-ueditor-wrap npm install vue-ueditor-wrap 4.在你所需要展示的页面 引入vue-ueditor-wrap 此时

Vue2 与 Vue3 的区别有哪些

Vue 2 和 Vue 3 在许多方面都有显著的区别,包括性能、API 设计、功能特性等。以下是它们主要的区别: 1. 响应式系统 Vue 2: 基于 Object.defineProperty: Vue 2 使用 Object.defineProperty 来实现响应式数据。这种方法在处理对象属性时有一定的局限性,比如不能检测到对象属性的添加或删除,以及数组的变更(如长度变化)。Vue 3:

vue2,vue3基于elementUI的el-table实现复制粘贴功能

vue2,vue3基于elementUI的el-table实现复制粘贴功能 vue2vue3 1、先声明一下,为啥又有vue2和vue3呢,因为老项目要改造成vite+ts+vue3,时间紧,来不及全部转换,所以就有了componentApi和optionsApi共存的情况 2、单页面使用,全局未实现 vue2 既然是基于el-table呢就有现成的methods可以使用 @

Vue2升级Vue3 --- 第三方库变化(基于gogocode)

本次升级基于gogocode快捷转换gogocode升级体验,汇总的部分问题可能与gogocode有关,但仍可作为vue2升级vue3过程中报错问题的解决参考 第三方库变化 1.vue-contextmenujs(右键菜单) // 原第三方库不支持vue3,更换为支持vue3的库"@imengyu/vue3-context-menu": "^1.0.8"// 更换库后组件样式与以前不

在 vue2 中实现 echarts 立体方形柱状图及立体圆柱

1、在做大屏项目时,为了页面不显得单调,有时设计会设计些立体的柱状图,前几天做大屏刚好遇到,记录一下。echarts本身没有配置直接配置立体图,立体图实质是三个图形合并堆积形成的视觉效果,分别是上面的盖,中间主体和下面的底,再配合中间主体的渐变颜色而实现。本文默认都是使用过echarts的,常规项不赘述,只看option的配置项,先上效果。 2、立体方块图  pdChartOptio