likes
comments
collection
share

🚀 微信小程序实现 swiper 滑动/释放查看详情效果

作者站长头像
站长
· 阅读数 15

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

大家好,我是疯狂的小波。最近在小程序中要实现一个图片切换 滑动查看详情的效果,如上图:切换到最后一张图片时,继续左滑,显示滑动查看详情模块,并且左滑指定距离后,文案变成释放查看详情,此时手势释放就会跳转到详情页;如果没有到指定距离释放则图片回到原位,什么都不做。

其实这样的效果在各大平台现在都用的非常多了。基本都是用于商品的头图。

看了下原生的 swiper 组件,并没有提供相关的功能。本来想自己实现一个类似 swiper 组件的效果,再加上滑动查看详情功能;但是由于开发周期较短,短时间内基本很难实现和 swiper 完全一样的功能和效果,所以就想能不能基于 swiper 组件进行扩展,来达到这个目标。这样也能够避免重复造轮子,并且自己实现的不一定有原生的好用。

接下来我们就来看看,如何基于 swiper 组件来实现这个效果。

方案尝试

最开始想的是,在最后一张图片上面增加一个遮罩层,在遮罩层上面绑定一个滑动事件,通过滑动事件的移动距离来控制 swiper 和 滑动查看更多模块 的位置,同时判断左滑超过指定距离时触发释放查看详情的状态。

理论来说这种方案是可行的,但是实际操作过程中发现,存在很多问题,如:swiper 滑动到最后一张图片,再左滑时是有阻尼效果的(图片滑动距离小于手势拖动距离,并且距离越大,阻尼效果越明显);而右滑没有阻尼效果,并且达到一定距离还会切换到上一张图片,而我们自己在遮罩层实现的滑动事件默认是没有这种效果的,这样就和原生的 swiper 效果不同步了。

虽然这种也可以解决,但是成本比较高,不符合我们的预期;并且显然也不是一个好的方案,原生的 swiper 一旦有这方便的改动,我们的实现又会不一定能契合。

最终方案

查看官方文档发现,swiper 组件提供 bindtransition 事件监听,也就是左右滑动时 swiper-item 位置改变的回调,基于这个回调事件,我们就可以拿到实际左右滑动距离了,而不用考虑阻尼效果的影响。(所以还是得多看文档啊)

那查看详情模块的显示位置处理呢?如果根据 transition 的回调移动距离来设置位置,会发现移动时存在抖动的情况,效果并不流畅,这是因为 transition 回调有一个类似节流的处理,并不是每移动1个像素都会触发回调,而是在一定距离或时间后才触发,所以无法保证效果的流畅性。

思考后发现,我们可以直接将这个模块放在最后一个图片的模块内,通过定位展示在图片右侧,这样左滑拖动时,模块就会自动显示了。并且滑动距离也能够保持与图片完全一致。

接下来只要实现:在最后一张图片左滑时,如果达到指定距离,变更查看文案,释放时触发查看详情事件,如果没有达到指定距离,什么都不做。

这个可以结合 touchstarttouchend 事件来处理。

大概流程如下:

🚀 微信小程序实现 swiper 滑动/释放查看详情效果

有了思路之后,代码就好实现了。我们来看下最终实现的代码吧。

wxml 页面:

// wxml代码
<swiper
  bind:transition="intervalTransition"
  bind:touchstart="swiperTouchStart"
  bind:touchend="swiperTouchEnd"
>
    <swiper-item wx:for="{{imageList}}" wx:key="*this">
      <image src="{{item}}" />
      <!-- 最后一张图片插入 滑动查看更多模块 -->
      <view wx:if="{{index + 1 === imageList.length}}" class="swiper-more-item">
        <view class="swiper-see-more {{isSwiperMore ? 'sure-more' : ''}}">
          <image class="image" src="/assets/images/left_more.png" />
          <text class="txt">
            {{isSwiperMore ? '释放查看更多' : '滑动查看更多'}}
          </text>
        </view>
      </view>
    </swiper-item>
</swiper>

滑动查看更多模块样式:

// 设置超出 swiper-item 模块显示,否则滑动查看更多模块会被隐藏
swiper-item {
  overflow: visible;
}

// 查看更多样式
.swiper-more-item {
  position: absolute;
  left: 100%;
  top: 0;
  width: 750rpx;
  height: 100%;
  margin-left: 24rpx;
  background: #f7f7f7;
  border-radius: 16rpx 0 0 16rpx;
  .swiper-see-more {
    width: 128rpx;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: space-evenly;
    .image {
      width: 32rpx;
      height: 32rpx;
    }
    .txt {
      width: 40rpx;
      font-size: 24rpx;
      color: #999999;
      line-height: 28rpx;
    }
    &.sure-more {
      .image {
        transform: rotate(180deg);
      }
    }
  }
}

js 事件处理:

// swiper手动滑动 - 开始
swiperTouchStart() {
    // 当前最后一张图片时,进行监听
    if (this.data.curIndex === imageList.length) {
      this.canSwiperLeft = true;
    }
}
// swiper滑动过程监听
intervalTransition(e: any) {
    if (!this.canSwiperLeft) return;
    // 根据滑动的偏移量判断是否达到查看详情状态
    const offset = e.detail.dx;
    const isSwiperMore = offset > SWIPER_MORE_RANGE;
    if (isSwiperMore !== this.data.isSwiperMore) {
      this.setData({
        isSwiperMore
      });
    }
}
// swiper手动滑动 - 释放
swiperTouchEnd() {
    if (!this.canSwiperLeft) return;
    this.canSwiperLeft = false;
    // 释放时,如果是查看详情状态,则执行指定方法
    if (this.data.isSwiperMore) {
      this.setData({
        isSwiperMore: false
      });
      this.toDetail();
    }
}

这样就可以实现我们想要的效果了,并且很好的利用了 swiper 本身的功能;和 swiper 进行了很好的结合。以最少的代码量实现我们的需求。

最终效果如下:

🚀 微信小程序实现 swiper 滑动/释放查看详情效果

第一次左滑释放时,未达到指定位置,不做处理;第二次左滑释放时,达到指定位置,跳转到详情页面。并且左滑到指定距离时,滑动查看更多文案变更为释放查看更多

总结

在小程序中要实现图片切换,滑动/释放查看详情的效果,可以合理的利用 swiper 组件本身的功能。

在样式上,可以在最后一张图片后插入滑动查看详情模块,并通过样式定位到指定位置,让模块的展示始终跟随 swiper 本身的滑动效果;

通过绑定 touchstart 事件,当处于最后一张图片时,才处理 swipertransition 事件,监听滑动位置的切换,根据滑动距离是否达到指定值来设置滑动状态,手势释放时触发 touchend 事件,根据滑动状态判断是否执行查看详情事件。

这样就能够实现我们想要的效果了,如果觉得有用顺便点个赞👍支持一下呗!

推荐阅读