【小程序】微信小程序webview渲染模式使用原生swiper实现“中间大,两边小,当前项始终在中间”的轮播图(带左右切换按钮、图片总数多于3张)

想要实现的效果如下图。查了一些组件都没有类似的效果,于是使用原生的swiper组件写了一个。但是只有列表长度大于3才能保持当前项始终在中间显示的效果。

主要逻辑就是根据current(swiper 当前索引)计算三屏视图中的居中项下标 centerIndex,居中项为 (current + 1) % 列表长度。

wxml:

    <view class="template-section-carousel">
      <swiper class="swiper-section" circular="true" current="{{current}}" display-multiple-items="3" duration="300" bindchange="onSwiperChange">
        <swiper-item wx:for="{{swiperList}}" wx:key="id">
          <image class="card {{index === centerIndex ? 'active' : ''}}" src="{{item.imgUrl}}" mode="widthFix" data-current-swiper-id="{{item.id}}" />
        </swiper-item>
      </swiper>

      <!-- 左右切换按钮 -->
      <block>
        <image src="/arrow-left.png" mode="widthFix" class="arrow left" bind:tap="handleArrowLeft" />
        <image src="/arrow-right.png" mode="widthFix" class="arrow right" bind:tap="handleArrowright" />
      </block>
    </view>

css:

.template-section-carousel {
  position: absolute;
  z-index: 2;
  width: 100%;
  height: auto;
  top: 910rpx;
  left: 0;

  .swiper-section {
    width: 578rpx;
    height: 282.67rpx;
    margin: 0 auto;

    swiper-item {
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .card {
      width: 145.33rpx;
      height: 208rpx;
      overflow: hidden;
      transform: scale(0.85);
      transition: transform 300ms ease, opacity 300ms ease, box-shadow 300ms ease;
    }

    .card.active {
      width: 197.33rpx;
      height: 282.67rpx;
      transform: scale(1);
    }
  }

  .arrow {
    position: absolute;
    z-index: 3;
    width: 26.67rpx;
    height: auto;
    top: 120rpx;
  }

  .left {
    left: 35rpx;
  }

  .right {
    right: 35rpx;
  }
}

js:

Page({
  data: {
    current: 0,
    centerIndex: 1,
    swiperList: [
      { id: 1, imgUrl: '/template-1.png' },
      { id: 2, imgUrl: '/template-2.png' },
      { id: 3, imgUrl: '/template-1.png' },
      { id: 4, imgUrl: '/template-2.png' }
    ]
  },

  onShow() {
    this.init()
  },

  /**
   * 初始化
   */
  init() {
    this.updateNeighbors(this.data.current)
  },


  /**
   * 轮播图切换,传入 current 计算中间可视项的 centerIndex
   */
  onSwiperChange(e) {
    const current = e.detail.current
    this.updateNeighbors(current)
  },


  /**
   * 最关键的部分,在这里计算居中项并加放大样式;
   * 根据传入的 current(swiper 当前索引),计算三屏视图中的居中项下标 centerIndex,
   * 并同步到数据;用于让中间项应用放大样式,保持“当前项始终居中放大”。
   * 注意:此处采用 display-multiple-items=3 且 circular=true,居中项为 (current + 1) % 列表长度。
   */
  updateNeighbors(current) {
    const len = this.data.swiperList.length
    const centerIndex = (current + 1) % len
    this.setData({ current, centerIndex })
  },

  /**
   * 切换上一张、下一张
   */
  handleArrowLeft() {
    const { current, swiperList } = this.data
    const newCurrent = (current - 1 + swiperList.length) % swiperList.length
    this.setData({ current: newCurrent })
    this.updateNeighbors(newCurrent)
  },

  handleArrowright() {
    const { current, swiperList } = this.data
    const newCurrent = (current + 1) % swiperList.length
    this.setData({ current: newCurrent })
    this.updateNeighbors(newCurrent)
  },
})

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值