VUE ———— Element Carousel 走马灯 源码分析与改写 (显示多张)

用过Element Carousel 组件的 应该都知道 ,他只能显示3个item, 而没有提供显示数量设置的属性,那如果想要显示多个,就要来改下他的源码,一起看下吧!

原本样式:

改动后:

首先在浏览器里先看下他的样式:

首先我们将隐藏的item 显示出来 发现他是这个样子的

 

我们会发现 他会在左面后者右面有两个item 是重叠的   其实不重叠 直接就可以用啦  哈哈  我们就在这个基础上面改就好了!

 

下面来看下代码: 首先carousel组件在element-ui/packages/carousel 就可以找到 主要是main.vue和item.vue两个文件

main.vue 这里不需要动,只需要改item.vue就可以,先看下item.vue的代码:

整个的处理主要有三个变量  

1. index : 每个item的原本索引值

2. activeIndex :  当前显示item的索引值  就是比例最大的那个

3. length: item的数量

下面看下 item.vue里面的方法:

 1. 这个方法是根据item的index和当前的activeIndex 以及 length 去重新排序item的位置的一个方法

2. 这个是在上面的方法之后,计算已经排序好的每个 item 的 偏移量

3. 再来看下这个方法 (代码中注释说明)

     translateItem(index, activeIndex, oldIndex) {
        const parentType = this.$parent.type;
        const parentDirection = this.parentDirection;
        const length = this.$parent.items.length;
        if (parentType !== 'card' && oldIndex !== undefined) {
          this.animating = index === activeIndex || index === oldIndex;
        }
        if (index !== activeIndex && length > 2 && this.$parent.loop) {
          // 这里调用上面第一个方法  计算每个item应该在的位置
          index = this.processIndex(index, activeIndex, length);
        }
        if (parentType === 'card') {
          if (parentDirection === 'vertical') {
            console.warn('[Element Warn][Carousel]vertical direction is not supported in card mode');
          }
          this.inStage = Math.round(Math.abs(index - activeIndex)) <= 1; // 这里变量用来判断class的  当前显示的和左右两个为true 提升了z-index 等级
          this.active = index === activeIndex; // 这个变量是用来判断当前主要展示的item  给了一个class  z-index 等级最高
          this.translate = this.calcCardTranslate(index, activeIndex); // 这里调用上面第二个方法 得到每个位置item的偏移量
          this.scale = this.active ? 1 : CARD_SCALE;
        } else {
          this.active = index === activeIndex;
          const isVertical = parentDirection === 'vertical';
          this.translate = this.calcTranslate(index, activeIndex, isVertical);
        }
        this.ready = true;
      },

Ok,下面是我修改后的 item.vue 完整代码

<template>
  <div
    v-show="ready"
    class="el-carousel__item"
    :class="{
      'is-active': active,
      'el-carousel__item--card': $parent.type === 'card',
      'is-in-stage': inStage,
      'specialIndex': specialIndex,
      'is-hover': hover,
      'is-animating': animating
    }"
    @click="handleItemClick"
    :style="itemStyle">
    <div
      v-if="$parent.type === 'card'"
      v-show="!active"
      class="el-carousel__mask">
    </div>
    <slot></slot>
  </div>
</template>

<script>
  import { autoprefixer } from 'element-ui/src/utils/util';
  const CARD_SCALE = 0.83;
  export default {
    name: 'ElCarouselItem',

    props: {
      name: String,
      label: {
        type: [String, Number],
        default: ''
      }
    },

    data() {
      return {
        hover: false,
        translate: 0,
        scale: 1,
        active: false,
        ready: false,
        inStage: false,
        specialIndex: false,
        animating: false
      };
    },

    methods: {
      processIndex(index, activeIndex, length) {
        if(activeIndex == 0) {
          return index==1?1:index==2?2:index==3?-3:index==4?-2:index==5?-1:0
        }
        if(activeIndex == 1) {
          return index==2?1:index==3?2:index==4?-3:index==5?-2:index==0?-1:0
        }
        if(activeIndex == 2) {
          return index==3?1:index==4?2:index==5?-3:index==0?-2:index==1?-1:0
        }
        if(activeIndex == 3) {
          return index==4?1:index==5?2:index==0?-3:index==1?-2:index==2?-1:0
        }
        if(activeIndex == 4) {
          return index==5?1:index==0?2:index==1?-3:index==2?-2:index==3?-1:0
        }
        if(activeIndex == 5) {
          return index==0?1:index==1?2:index==2?-3:index==3?-2:index==4?-1:0
        }
      },

      calcCardTranslate(index, activeIndex) {
        return index * 80 * 2
      },

      calcTranslate(index, activeIndex, isVertical) {
        const distance = this.$parent.$el[isVertical ? 'offsetHeight' : 'offsetWidth'];
        return distance * (index - activeIndex);
      },

      translateItem(index, activeIndex, oldIndex) {
        const parentType = this.$parent.type;
        const parentDirection = this.parentDirection;
        const length = this.$parent.items.length;
        if (parentType !== 'card' && oldIndex !== undefined) {
          this.animating = index === activeIndex || index === oldIndex;
        }
        index = this.processIndex(index, activeIndex, length);
        if (parentType === 'card') {
          if (parentDirection === 'vertical') {
            console.warn('[Element Warn][Carousel]vertical direction is not supported in card mode');
          }
          this.inStage = Math.round(Math.abs(index)) <= 1;
          this.specialIndex = Math.round(Math.abs(index)) >= 3;
          this.active = index === 0;
          this.translate = this.calcCardTranslate(index, activeIndex);
          this.scale = Math.abs(index)==0 ? 1 : Math.abs(index)==1? 0.83 : Math.abs(index)==2? 0.73 : Math.abs(index)==3? 0.65 : 0.58;
        } else {
          this.active = index === activeIndex;
          const isVertical = parentDirection === 'vertical';
          this.translate = this.calcTranslate(index, activeIndex, isVertical);
        }
        this.ready = true;
      },

      handleItemClick() {
        const parent = this.$parent;
        if (parent && parent.type === 'card') {
          const index = parent.items.indexOf(this);
          parent.setActiveItem(index);
        }
      }
    },

    computed: {
      parentDirection() {
        return this.$parent.direction;
      },

      itemStyle() {
        const translateType = this.parentDirection === 'vertical' ? 'translateY' : 'translateX';
        const value = `${translateType}(${ this.translate }px) scale(${ this.scale })`;
        const style = {
          transform: value
        };
        return autoprefixer(style);
      }
    },

    created() {
      this.$parent && this.$parent.updateItems();
    },

    destroyed() {
      this.$parent && this.$parent.updateItems();
    }
  };
</script>
<style>
  .el-carousel__arrow--left {
    left: -426px
  }
  .el-carousel__arrow--right {
    right: -25px;
  }
  .el-carousel__item {
    cursor: pointer;
    z-index: 1;
  }
  .el-carousel__item--card.is-in-stage {
    z-index: 2;
  }
  .el-carousel__item--card.is-active {
    z-index: 3;
  }
  .specialIndex{
    z-index: 0
  }
</style>

主要就是在上面提到的三个方法上面做了改动,我只显示六张,所以就是按照显示6张 写死的值,懒得计算啦  哈哈哈  但是大致思路就是这样  如果显示数量不一样 数值稍作改动就可以啦!

  • 12
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 22
    评论
根据引用提到的,使用element-plus的el-carousel组件来放置滚动广告时,可以通过设置type="card"来实现效果。至于走马灯图片的大小,文档并没有具体说明。 根据引用的解决方法,可以为carousel组件添加显示条件list.length > 0,只有当list不为null且长度大于0时才会渲染元素。这意味着走马灯图片的大小可能取决于绑定给el-carousel的数据list的元素数量和大小。 引用提到,el-carousel绑定的数据需要一个初始值。如果初始值为空数组([]),可能会出现异常。所以可以通过为初始值提供一些图片元素,比如var bannerList = ref([1, 2, 3]),来确保开始时就有一些图片展示在走马灯,从而确定走马灯图片大小。 综上所述,element-plus carousel走马灯图片大小是由绑定给el-carousel的数据图片元素数量和大小决定的。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [element-plus 之el-carousel 走马灯 加载图片刚进入的时候为什么数据显示不对?](https://blog.csdn.net/weixin_43136717/article/details/128233256)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Vue3 + Element-Plus carousel走马灯 显示动态数据时 默认会显示一个空白元素](https://blog.csdn.net/qq_40007006/article/details/120440831)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mickey_于浩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值