vue实现图片滚动(类似走马灯效果)

上次写了一个简单的图片轮播,这个相当于在上面的一些改进。这个组件除了可以进行图片滚动外,也可以嵌入任何内容的标签进行滚动,里面用了slot进行封装。

父:

<template>
   <div id="app">
      <er-carousel-index :typeNumber=2 :pageNumber=3  :timeSpace=2 :duration=2 :isOrNotCircle="true"  url="/src/js/index.json" :isOrNotButton=false>
            <template scope="props">-----使用子组件传过来的值,封装slot
                <div class="articleList-box-photo ">
                    <div class="tu imageEffectsAnimate imageEffects_Magnifier">
                        <a>
                            <img class="minMax" :src="props.item.img">
                        </a>
                    </div>
                </div>
                <div class="articleList-box-title">
                    <div class="title">
                        <a class="textleft">{{props.item.title}}</a>
                    </div>
                </div>
            </template>
        </er-carousel-index>
   </div>
</template>
<script>
   import ErCarouselIndex from './components/carouselIndex/src/carouselIndex.vue'
   export default {
      name: 'app',
      data() {
            }
               },
      components: {
         ErCarouselIndex//一定要进行组件声明,不然不能引用子组件
      }
   }
</script>

子组件:
<template>
    <div tag="div" class="articleList articleListMod-3 er-carouseindex" name="slide-fade" id="articleList" :style="{height:imgHeight+'px'}" >
        <span id="btn1" class="er-carouseindex-left" @mousedown="imgMove('mouseLeft')" @mouseup="cancelMove('left')" v-show="isOrNotButton"></span>
        <span id="btn2" class="er-carouseindex-right"  @mousedown="imgMove('mouseRight')" @mouseup="cancelMove('right')" v-show="isOrNotButton"></span>
        <div id="packageAll" class="er-carouseindex-con" @mouseover="clearAuto" @mouseout="slideAuto">
            <div class="er-carouseindex-bar" v-show="isOrNotCircle">
                <div v-for="(item,dex) in imgList" @mouseup="clearAuto" class="er-carouseindex-circle" @click="circleClick(dex)" :class="{circleSelected:dex===indexCircle}">
                </div>
            </div>
            <div id="imageAll" class="er-carouseindex-item" :style="{transform:translateX,transition:transFlag?transitionTime:''}">
                <div class="articleList-box er-carouseindex-box" v-for="(list,index) in imgLisShow" :style="{width:imgWidth+'%'}"
                     style="max-height:50%;">
                    <slot :item="list"></slot>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
    export default
    {
        name: "ErCarouselIndex",
        data(){
            return {
                imgList: [],//请求接口数据
                imgLisShow: [],//图片滚动数据,包括左中右三种
                timer: null,//自动循环滚动时的间隔时间
                timeout:null,//长按时的图片滚动间隔时间
                index:0,//图片索引
                translateXnum:0,//图片滚动时的偏移量
                translateX:"",//生成图片偏移时的表达式
                imgWidth:"",//图片所占宽度
                timeDown:"",//鼠标刚按下时的时间
                timeup:"",//鼠标松开时的时间
                clickSpace:"",//鼠标按下松开的时间间隙
                transFlag:true,//是否匀速滚动,
                transitionTime:"",
                indexCircle:0//小圆圈滚动索引
            }
        },
        props:{
            duration:0,//图片延时滚动
            typeNumber:0, //每次滚动几张
            timeSpace:0,  //图片滚动时间间隔
            url:String,//请求接口地址
            pageNumber:0,//当前页面显示几张图片
            isOrNotButton:true,//是否显示左右按钮
            isOrNotCircle:true,//是否显示小圆圈
            imgHeight:""//图片滚动显示高度
        },
        watch:{
            index:{
                handler(){
                    var _this=this;
                   if(Math.abs(this.index)==this.imgList.length){
                       this.indexCircle=0;
                      setTimeout(function(){
                          _this.reset();
                      },_this.duration*1000*0.98);
                   }else{
                       this.indexCircle=this.index;
                   }
                    this.calcXnum();
                 }
            },
            translateXnum:{
                handler(){
                    this.translateX="translateX("+this.translateXnum+"%)";
                }
            }
        },
        methods:{
            //页面初始化复赋值
            imgView:function() {
                var _this = this;
                _this.$http.get(_this.url).then(function (res) {
                    _this.imgList = res.data.imgList;
                    for(var i=0;i<3;i++){
                        _this.imgList.forEach(function (item, index) {
                            _this.imgLisShow.push(item);

                        });
                    }
                    _this.reset();
                    _this.slideAuto();
                    _this.imgWidth=(100/_this.pageNumber)-1;
                    _this.transitionTime="all "+_this.duration*0.98+"s linear";
                    console.log(_this.transitionTime);
                });
            },
            //图片滚动方法(长按)
            imgMove:function(direct){
                var _this = this;
                _this.timeDown=new Date();//记录按下的时间
                _this.timeout = setInterval(function() {
                    if(direct=="mouseLeft") {
                        _this.leftMove();
                    }else{
                        _this.rightMove();
                    }
                },300);
            },
            //鼠标送开时执行的方法
            cancelMove:function(direct){
                var _this = this;
                _this.clearAuto();
                this.timeup=new Date();//记录松开的时间
                this.clickSpace=this.timeup.getTime() - this.timeDown.getTime();
                //时间间隔小于500毫秒为点击,反之为长按
                if(this.clickSpace<500){
                    for(var i=0;i<_this.typeNumber;i++){
                        if(direct=="left"){
                            _this.leftMove();
                        }else{
                            _this.rightMove();
                        }
                    }
                }
                if (this.timeout) {
                    clearInterval(this.timeout);
                    this.timeout = null;
                }
            },
            //向左移动
            leftMove:function(){
                this.index--;
                this.transFlag=true;
            },
            //向右移动
            rightMove:function(){
                this.transFlag=true;
                this.index++;
            },
            slideAuto:function () {
                var _this = this;
                _this.timer = setTimeout(function () {
                    if(Math.abs(_this.index)!==_this.imgList.length){
                        _this.rightMove();
                        _this.slideAuto();
                    }
                }, _this.timeSpace * 1000);
            },
            clearAuto:function () {
                console.log("停止");
                if (this.timer) {
                    clearInterval(this.timer);
                    this.timer = null;
                }
            },
            //重置
            reset:function(){
                this.index=0;
                this.transFlag=false;
                this.calcXnum();
            },
            calcXnum:function(){
                var _this=this;
                this.translateXnum=-(this.index+this.imgList.length)*(100/this.pageNumber);
            },
            //点击圆圈跳转图片
            circleClick:function(dex){
                this.index=dex;
                this.clearAuto();
            }
        },
        mounted()
        {
            this.$nextTick(function () {
                this.imgView();
            });
        }
    }
</script>


这个组件相对来说功能比较完整,用户可以通过传参来控制当前页面需要显示几张图片,图片滚动时间间隔,是否显示左右点击按钮等等,详细参数可以查看props,里面都有注释。

以下是一个简单的 Vue 组件实现文字横向无缝走马灯效果的实例代码: ```vue <template> <div class="marquee"> <div class="marquee-inner" ref="marquee"> <slot></slot> <slot></slot> </div> </div> </template> <script> export default { name: 'Marquee', data() { return { animationId: null, speed: 1, offset: 0, innerWidth: 0, marqueeWidth: 0 } }, mounted() { this.startAnimation() }, beforeDestroy() { this.stopAnimation() }, methods: { startAnimation() { this.animationId = requestAnimationFrame(this.animate.bind(this)) }, stopAnimation() { cancelAnimationFrame(this.animationId) }, animate() { this.offset -= this.speed if (this.offset < -this.marqueeWidth) { this.offset = 0 } this.$refs.marquee.style.transform = `translateX(${this.offset}px)` this.animationId = requestAnimationFrame(this.animate.bind(this)) }, updateDimensions() { this.innerWidth = this.$refs.marquee.clientWidth this.marqueeWidth = this.$refs.marquee.scrollWidth } }, mounted() { window.addEventListener('resize', this.updateDimensions) this.updateDimensions() }, beforeDestroy() { window.removeEventListener('resize', this.updateDimensions) } } </script> <style scoped> .marquee { overflow: hidden; white-space: nowrap; } .marquee-inner { display: inline-block; animation: none; } </style> ``` 该组件包含一个名为 `Marquee` 的 Vue 组件,它具有以下功能: - 在组件内部包含一个具有 `marquee-inner` 类名的 div 元素,用于包含实际的滚动内容。 - 使用 `requestAnimationFrame` API 实现动画效果。 - 使用 `translateX` CSS 属性在水平方向上移动滚动内容。 - 监听窗口大小变化事件,并在更新时重新计算滚动内容的宽度。 使用该组件时,只需要将需要滚动的内容放入组件的插槽中即可: ```vue <marquee> <span>这是滚动的文字1</span> <span>这是滚动的文字2</span> <span>这是滚动的文字3</span> <span>这是滚动的文字4</span> </marquee> ``` 你可以根据需要自定义组件的样式,例如设置滚动速度等。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值