小程序轮播,上下两层图片,底层渐变淡入淡出,上层动画划入效果

先看效果: 如果大家有喜茶小程序,可以进入查看首页轮播效果图,大概就是那个效果。

捋一下我开发过程的思路,一共有两个。

第一个思路: 用微信小程序的组件,swiper实现上层透明照片的轮播效果,底层的照片根据swiper组件的bindchange,bindtransition,bindanimationfinish三个方法组合使用来实现轮播左右滑动的过程中,opacity的变化以及上下索引的变化,进而根据索引来更换底层的照片,底层是写了两层图片,动态手动的更换背景图以及处理opacity的值的变化。由于swiper在切换过程中,其实有两个索引,一个是当前的一个是下一个的,分别是index 与 current , 他们会在某一个时刻不同但是更多时候索引是相同的,导致opacity在轮播自动播放的情况下,淡入淡出的效果不明显。所以最终效果实现了90%,最后10%的效果没有解决思路,虽然产品说实在没办法也可以但是自己依然觉得不太好。

第二个思路: 上层的透明图片部分依然不变,使用微信小程序组件swiper实现轮播的变换,但是底层的照片淡入淡出效果直接使用一个数组填充底层图片的地址来显示,根据轮播的索引,直接底层图片的索引与上层轮播的索引对应上的时候直接opacity展示为1,其他索引下的opacity则为0。原理类似前端经常用active来设置选中的项目展示不同的样式。此种方法简便效果100%,可惜自己一开始没有想到。

重点代码如下:

<view wx:if="{{swiperImgs.length}}" style="position: relative">
  
  <view class="qm-banner-underImg uperUderImg">
    <view class="aaaa" wx:for="{{underImgList}}" wx:key="index" style="opacity:{{index == currentIndex?'1':'0'}};">
      <image lazy-load src="{{item.underImg}}" style="width: 100%">image>
    view>
  view>
  <swiper
    class="v-qm-banner"
    style="{{miniStyle}}"
    autoplay="{{true}}"
    circular
    indicator-active-color="{{indicatorStyle}}"
    data-index="{{currentIndex}}"
    bindchange="swiperChange"
  >
    <swiper-item class="swiper-item" wx:for="{{ swiperImgs}}" wx:key="index">
      <view catchtap="bindLink" data-item="{{item}}" style="height:{{filter.styleToObj(data.miniStyle).height}};">
        <image lazy-load mode="widthFix" class="image" src="{{item.img}}">image>
      view>
    swiper-item>
  swiper>
view>

import { $component } from '@/libs/mpext'
import { getSwiperImages } from './banner'
const app = getApp()

$component({
  mapState: [],
})({
  properties: {
    data: {
      type: Object,
      value: {},
      observer(val) {
        if (!val) return
        this.handleSwiperData()
      },
    },
    index: {
      type: Number,
      value: 0,
    },
  },
  data: {
    currentIndex: 0,
  },
  pageLifetimes: {
    show() {
      this.handleSwiperData()
    },
  },
  methods: {
    handleSwiperData() {
      const { data } = this.data
      const imgs = data?.propsValue?.imgs || []

      // 过滤下当前可显示的数据
      const swiperImgs = getSwiperImages(imgs)
      const underImgList = []
      swiperImgs.forEach((ele, index) => {
        underImgList.push({ index: index, underImg: ele.underImg })
      })
      this.setData({
        underImgList,
      })
    },

    // 轮播变动
    swiperChange(currnet) {
      const currentIndex = currnet.detail.current
      this.setData({
        currentIndex,
      })
    },
  },
})

// banner
.v-qm-banner {
  z-index: 999;
  background: transparent;

  .image {
    width: 100%;
  }

  .qm-banner-swiper-item {
    position: relative;
  }

  .underImg {
    position: absolute;
    top: 0;
    left: 0;
    z-index: -1;
    width: 100%;
    height: 390rpx;
  }

  .qm-banner-swiper-item-box {
    background-size: cover;
    opacity: 0;
    transition-property: opacity;
  }
}

.qm-banner-underImg {
  position: absolute;
  left: 50%;
  transform: translate(-50%);
}

.uperUderImg {
  width: 100%;
  height: 100%;
}

.aaaa {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  transform: translate(0%, 0) translateZ(0);
  transition: 1s;
}

你可能感兴趣的:(微信小程序,小程序,前端)