微信原生小程序首撸3D层叠轮播图,无限轮播,自动轮播

118 阅读3分钟

微信小程序原生轮播图只有单边的层叠样式,没有两边层叠样式轮播图,文字描述懒得写,有疑问的可私信作者,不喜勿喷,直接上效果图与代码:

![{XQX93FN00{$T{W]XK~BHHF.png](p9-juejin.byteimg.com/tos-cn-i-k3…)

<view class="sound-container">
  <view bind:touchstart="onTouchStart" bind:touchend="onTouchEnd" bind:touchmove="onTouchMove" class="swiper-view">
    <block wx:for="{{soundDataList}}" wx:key="key">
      <view bind:tap="onDetail" data-item="{{item}}" class="item {{item.class}}">
        <view class="item-view">
          <image class="sw-image" src="{{item.coverUrl}}" mode="aspectFill" />
          <view class="sound-name-view" wx:if="{{currentIndex === index}}">
            <view>{{item.mainTitle}}</view>
            <view class="sub-title">{{item.subTitle}}</view>
          </view>
        </view>
      </view>
    </block>
  </view>
</view>
let timer = null
// case-1/index.js
let touchStartX = 0;
const conunt = 30
Component({
  /**
   * 组件的属性列表
   */
  properties: {

  },

  /**
   * 组件的初始数据
   */
  data: {
    soundDataList: [ { "audioLibId": "329", "headTextShow": 0, "mainTitle": "小七孔", "subTitle": "跟着声音游贵州", "coverUrl": "https://object.gcongo.com.cn/onecode-travel/nonClassic/5c44075672d00af1177097d171dba3fa/2024/4/1713160007150/57928e35af974a6db4be7457c218ce9d.png", },
      { "audioLibId": "330", "headTextShow": 0, "mainTitle": "遵义会议会址", "subTitle": "跟着声音游贵州", "coverUrl": "https://object.gcongo.com.cn/onecode-travel/nonClassic/5c44075672d00af1177097d171dba3fa/2024/4/1713160265922/9b5667bdb4804b1496b7a456e31f5a5e.png", },
      { "audioLibId": "331", "headTextShow": 1, "mainTitle": "梵净山", "subTitle": "跟着声音游贵州", "coverUrl": "https://object.gcongo.com.cn/onecode-travel/nonClassic/5c44075672d00af1177097d171dba3fa/2024/4/1713159882375/d3c84da1d30141f0a67ef8623501dc89.png", },
      { "audioLibId": "332", "headTextShow": 0, "mainTitle": "黄果树瀑布", "subTitle": "跟着声音游贵州", "coverUrl": "https://object.gcongo.com.cn/onecode-travel/nonClassic/5c44075672d00af1177097d171dba3fa/2024/4/1713159338146/d5cd7122bb8840aa9350ab4d283d1e3d.png", },
      { "audioLibId": "333", "headTextShow": 1, "mainTitle": "坝陵河大桥", "subTitle": "跟着声音游贵州", "coverUrl": "https://object.gcongo.com.cn/onecode-travel/nonClassic/acc9f028cb4ea63295407f7ca9264cc2/2024/4/1713181483857/09c5732281494598993e420ad67661b4.jpg", },
      { "audioLibId": "334", "headTextShow": 1, "textDescription": "中国最后一个枪手部落", "mainTitle": "中国最后一个枪手部落", "subTitle": "中国最后一个枪手部落", "coverUrl": "https://object.gcongo.com.cn/onecode-travel/nonClassic/c380c609457851bfc3ea4e64c2ab71d2/2024/4/1713422546365/b2e9531136b5443fa3dcdfc2aed6cb8e.jpg" }],
    autoplay: false,
    duration: 500, // 动画时长
    interval: 3,
    currentIndex:0,
    list:[]
  },
  pageLifetimes: {
    load: function () {
      // this.initData()
        this.clearTimer()
        this.initData(true)
    },
    show: function () {
      this.setData({
        autoplay: true
      })

    },
    hide: function () {
      this.setData({
        autoplay: false
      })
    }
  },
  
  /**
   * 组件的方法列表
   */
  methods: {
    
    // isFirstInitData 是否是初始化数据,true 时启动定时器轮播
    initData(isFirstInitData) {
      let arrLength = this.data.soundDataList.length
      let currentIndex = this.data.currentIndex
      // console.log("currentIndex===",currentIndex);
      let list = this.data.soundDataList.map((item, index) => {
        let previousIndex1 = currentIndex - 1 < 0 ? arrLength - 1 : currentIndex - 1
        let previousIndex2 = currentIndex - 2 < 0 ? (arrLength) + (currentIndex - 2) : currentIndex - 2
        let nextIndex1 = currentIndex + 1 > arrLength - 1 ? 0 : currentIndex + 1
        let nextIndex2 = currentIndex + 2 > arrLength - 1 ? 0 + (currentIndex + 2) - arrLength : currentIndex + 2
        if (index === previousIndex1 && currentIndex !== previousIndex1) {
          item.class = 'item2'
        }
        if (index === previousIndex2  && currentIndex !== previousIndex2) {
          item.class = 'item1'
        }
        if (index === nextIndex1 && currentIndex !== nextIndex1) {
          item.class = 'item3'
        }
        if (index === nextIndex2  && currentIndex !== nextIndex2) {
          item.class = 'item4'
        }
        if (index === currentIndex) {
          item.class = 'item0'
        }
        return item
      })
      
      this.setData({
        soundDataList:list
      },() => {
        if(isFirstInitData){
          this.autoPlaySwiper()
        }
      })
    },
    onDetail({ currentTarget: { dataset: { item } } }) {
      console.log('item==', item);
    },
    onTouchStart(e) {
      console.log("滑动")
      this.clearTimer()
      touchStartX = e.touches[0].clientX; // 记录初始触点X坐标
    },
    onTouchMove(e) {
      // 阻止默认滚动行为
      // e.preventDefault();
    },
    onTouchEnd(e) {
      const touchEndX = e.changedTouches[0].clientX; // 获取结束触点X坐标
      const distanceX = touchEndX - touchStartX; // 计算滑动距离
     
      // 右滑
      if (distanceX > conunt) {
        // moveDirection = 'right';
        this.previousClick(true)
        // this.
      } else if (distanceX < -conunt) {
         // 左滑
       this.nextClick(true)
      } else {
        // moveDirection = ''; // 没有明显滑动或滑动距离太小
      }
   
    },
    previousClick(isTouch = false) {
      let currentIndex = this.data.currentIndex
      if (currentIndex === 0) {
        currentIndex = this.data.soundDataList.length - 1
      } else {
        currentIndex = currentIndex - 1
      }
      this.setData({
        currentIndex
      })
      this.initData(isTouch)
    },
    // isTouch 是否是滑动结束调用
    nextClick(isTouch = false) {
      let currentIndex = this.data.currentIndex
      if (this.data.soundDataList.length - 1 === currentIndex) {
        currentIndex = 0
      } else {
        currentIndex += 1
      }
      this.setData({
        currentIndex
      })
      this.initData(isTouch)
    },
    autoPlaySwiper(){
      //如果定时器存在则不在创建,防止滑动过快
      if(timer){
        return
      }
      timer = setInterval(() => {
        if(!this.data.autoplay){
          this.clearTimer()
          return
        }
        this.nextClick()
      }, this.data.interval * 1000 + this.data.duration);
    },
    // 如果定时器存在,清除定时器
    clearTimer(){
      if(timer){
        clearInterval(timer)
        timer = null
      }
    }


  }
})
/* components/home/sound-guizhou/index.wxss */
.sound-container {
  padding: 36rpx 0 50rpx 0;
  background-color: white;
}


.swiper-view {
  /* width: 100%; */
  background-color: white;
  width: calc(100% - 30px);
  display: flex;
  position: relative;
  justify-content: center;
  overflow: hidden;
  align-items: center;
  height: 434rpx;
  margin: 0 30rpx;
  --sWidth:398.4rpx;
  --sHeight:347.2rpx;
  --tWidth:298.8rpx;
  --tHeight:260.4rpx;
  --margin:44rpx
}
.item {
  width: var(--tWidth);
  height: var(--tHeight);
  position: absolute;
  border-radius: 16rpx;
  /* transition: 0.5s ease-out; */
  transition:  width 0.5s ease-out, height 0.5s ease-out;
  z-index: 995;
}
.item-view {
  width: 100%;
  height: 100%;
  border-radius: 16rpx;
  position: relative;
}
.sound-name-view {
  position: absolute;
  background: linear-gradient(270deg, rgba(103, 189, 237, 0) 0%, #238cc8 100%);
  font-size: 32rpx;
  color: #ffffff;
  font-weight: 600;
  bottom: 30rpx;
  left: 0;
  right: 0;
  padding: 27rpx 44rpx;
}
.sub-title {
  font-size:24rpx;
  font-weight:400;
  margin-top: 10rpx;
}
.sw-image {
  width: 100%;
  height: 100%;
  border-radius: 16rpx;
}
.item0 {
  z-index: 1000;
  width: 498rpx;
  height: 434rpx;
}
.item1 {
  left: 0;
  z-index: 997;
  width: var(--tWidth);
  height: var(--tHeight);

}
.item2 {
  left: var(--margin);
  z-index: 998;
  width: var(--sWidth);
  height: var(--sHeight);
}

.item3 {
  right: var(--margin);
  z-index: 998;
  width: var(--sWidth);
  height: var(--sHeight);
}


.item4 {
  right: 0;
  z-index: 997;
  width: var(--tWidth);
  height: var(--tHeight);
}