记录下手写渐进渐出式Banner轮播图

860 阅读2分钟

最近项目中做了一个轮播图,类似于下图腾讯云首页这种。不想用现成的组件,所以自己写了把它抽成了组件 image.png 先上代码:

html部分

写成这样是考虑每一个banner的结构是不一样的,一样的话可以写成v-for更优雅(图片的动态引用需要加require)

 <div class="banner">
    <ul ref="titleboxList" class="banner__list" @mouseover="bannerStop" @mouseleave="bannerStart">
      <li class="banner__item" :class="titleListIndex === 1 ? 'check' : 'uncheck'">
        <div class="banner__item-1">
          <div class="left">
            <span class="left-hd">banner1</span>
            <span class="left-btn1">了解更多</span>
            <div>
              <span class="left-btn2">立即咨询</span>
              <span class="left-btn3">解决方案手册</span>
              <span class="left-btn4">立即试用</span>
            </div>
          </div>
          <div class="right"><img src="titleItem1.png" alt="" /></div>
        </div>
      </li>
      <li class="banner__item" :class="titleListIndex === 2 ? 'check' : 'uncheck'">
        <div class="banner__item-1">
          <div class="left">
            <span class="left-hd">banner2</span>
            <span class="left-btn1">了解更多</span>
            <div>
              <span class="left-btn2">立即咨询</span>
              <span class="left-btn3">解决方案手册</span>
              <span class="left-btn4">立即试用</span>
            </div>
          </div>
          <div class="right"><img src="titleItem1.png" alt="" /></div>
        </div>
      </li>
      <li class="banner__item" :class="titleListIndex === 3 ? 'check' : 'uncheck'">
        <div class="banner__item-1">
          <div class="left">
            <span class="left-hd">banner3</span>
            <span class="left-btn1">了解更多</span>
            <div>
              <span class="left-btn2">立即咨询</span>
              <span class="left-btn3">解决方案手册</span>
              <span class="left-btn4">立即试用</span>
            </div>
          </div>
          <div class="right"><img src="titleItem1.png" alt="" /></div>
        </div>
      </li>
      <li class="banner__item" :class="titleListIndex === 4 ? 'check' : 'uncheck'">
        <div class="banner__item-1">
          <div class="left">
            <span class="left-hd">banner4</span>
            <span class="left-btn1">了解更多</span>
            <div>
              <span class="left-btn2">立即咨询</span>
              <span class="left-btn3">解决方案手册</span>
              <span class="left-btn4">立即试用</span>
            </div>
          </div>
          <div class="right"><img src="titleItem1.png" alt="" /></div>
        </div>
      </li>
    </ul>
    <div class="banner__ctrl">
      <ul @mouseover="bannerStop" @mouseleave="bannerStart">
        <li class="banner__ctrl-item" @click="titleListIndex = 1">
          <a :class="titleListIndex === 1 ? 'check' : ''"></a>
        </li>
        <li class="banner__ctrl-item" @click="titleListIndex = 2">
          <a :class="titleListIndex === 2 ? 'check' : ''"></a>
        </li>
        <li class="banner__ctrl-item" @click="titleListIndex = 3">
          <a :class="titleListIndex === 3 ? 'check' : ''"></a>
        </li>
        <li class="banner__ctrl-item" @click="titleListIndex = 4">
          <a :class="titleListIndex === 4 ? 'check' : ''"></a>
        </li>
      </ul>
    </div>
    </div>

样式部分css

用了scss

.banner {
  &__list {
    width: 1200px;
    height: 427px;
  }

  &__ctrl {
    position: absolute;
    top: 300px;
    width: 100%;

    &-item {
      display: inline-block;
      width: 26px;
      height: 25px;
      margin: 0 4px;
      cursor: pointer;

      a {
        display: inline-block;
        width: 26px;
        height: 5px;
        background: #35465a;
        border-radius: 3px;
      }
    }

    .check {
      background: #5375ff;
    }
  }

  &__item {
    position: absolute;

    @mixin afterMixin {
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      height: 420px;
      content: '';
      opacity: 0.1;
    }

    @mixin btnMixin {
      display: block;
      padding: 0 3px;
      height: 32px;
      margin-top: 20px;
      font-size: 14px;
      font-weight: 500;
      line-height: 32px;
      border-radius: 2px;
    }

    &-1::after {
      @include afterMixin;
      background: url(titleboxback.png);
    }

    &-1 {
      width: 1200px;
      height: 427px;

      .left {
        position: absolute;
        top: 106px;
        left: 130px;
        z-index: 100;
        display: flex;
        flex-direction: column;

        &-hd {
          font-size: 34px;
          font-weight: 500;
          line-height: 48px;
          color: #87cbff;
          text-align: left;
        }

        &-btn1 {
          @include btnMixin;
          color: #e8e8e8;
          border: 1px solid #e8e8e8;
        }

        &-btn2 {
          @include btnMixin;
          color: #fff;
          background: #1677ff;
        }

        &-btn3 {
          @include btnMixin;
          background: #fff;
        }

        &-btn4 {
          @include btnMixin;
          color: #fff;
          background: #ff6010;
        }

        span {
          cursor: pointer;
        }
      }

      .right {
        position: absolute;
        top: 88px;
        right: 0;
      }
    }

    &-2::after {
      @include afterMixin;
      background-color: red;
    }

    &-3::after {
      @include afterMixin;
      background-color: yellow;
    }

    &-4::after {
      @include afterMixin;
      background-color: green;
    }

    .check {
      opacity: 1 !important;
    }
  }

  .check {
    animation: showtip 0.7s 1;
    animation-fill-mode: forwards;
  }

  .uncheck {
    animation: hidetip 0.5s 1;
    animation-fill-mode: forwards;
  }

  @keyframes showtip {
    from {
      opacity: 0;
    }

    to {
      opacity: 1;
    }
  }

  @keyframes hidetip {
    0% {
      opacity: 1;
    }

    100% {
      display: none;
      opacity: 0;
    }
  }
}

js逻辑部分

export default {
  name: 'TitleBanner',
  data() {
    return {
      titleListIndex: 1,
      bannerInterval: null //轮播计时事件
    }
  },
  mounted() {
    this.bannerStart()
  },
  beforeDestroy() {
    this.bannerStop()
  },
  methods: {
    bannerStart() {
      let self = this
      if (this.bannerInterval != null) {
        this.bannerStop()
      }
      this.bannerInterval = window.setInterval(self.bannerOvers, 4000)
    },
    bannerStop() {
      window.clearInterval(this.bannerInterval)
      this.bannerInterval = null
    },
    bannerOvers() {
      let titleboxListArr = Array.from(this.$refs.titleboxList.children)
      if (this.titleListIndex === titleboxListArr.length) {
        this.titleListIndex = 1
      } else {
        this.titleListIndex = this.titleListIndex + 1
      }
    }
  }
}

思路

说一下大致的思路,页面开始执行setInterval,鼠标滑入时终止setInterval事件,我在这里的banner__ctrl部分因为设置了最上层,所以这个也要单独加划入划出事件。渐进渐出的效果用的是动画实现,比较简单,不过记得在消失时要设置display: none。 也没看什么攻略,全是自己想着写的,设计简单,有什么建议个批评都可以指正。