• 微信小程序实现堆叠式轮播


    1. 微信小程序实现堆叠式轮播

      初始需要给item们放置好位置以及各种层级,然后在切换滑动的过程中对设置的位置、层级、透明度进行替换,加上小程序的wx.createAnimation()动画效果。

    1.1. 方案一

    在这里插入图片描述

    1.1.1. banner.xml

    <view class="swiper-page" bindtouchmove="touchmove" bindtouchstart="touchstart" bindtouchend="touchend">
      <view wx:for="{{imgArray}}" wx:key="index" class="swiper-container">
        <view class="item-container" style="z-index:{{indexArray[index]}}">
          <view class="item{{index}} item-common" animation="{{animation[index]}}" data-text="{{textArray[index]}}">
            <image class="background" src="{{item.image}}" mode='aspectFit'></image>
            <text class="item-text">{{item.text}}</text>
          </view>
        </view>
      </view>
      <view bindtap="tapLeft" style="position:absolute;top:0;left:20rpx">往左滑</view>
      <view bindtap="tapRight" style="position:absolute;top:0;right:20rpx">往右滑</view>
    </view>
    

    1.1.2 banner.wxss

    <view class="swiper-page" bindtouchmove="touchmove" bindtouchstart="touchstart" bindtouchend="touchend">
      <view wx:for="{{imgArray}}" wx:key="index" class="swiper-container">
        <view class="item-container" style="z-index:{{indexArray[index]}}">
          <view class="item{{index}} item-common" animation="{{animation[index]}}" data-text="{{textArray[index]}}">
            <image class="background" src="{{item.image}}" mode='aspectFit'></image>
            <text class="item-text">{{item.text}}</text>
          </view>
        </view>
      </view>
      <view bindtap="tapLeft" style="position:absolute;top:0;left:20rpx">往左滑</view>
      <view bindtap="tapRight" style="position:absolute;top:0;right:20rpx">往右滑</view>
    </view>
    

    1.1.3 banner.js

    // 位置列表
    let posArray =    [ 280,120,420]
    // 缩放列表
    let scaArray = [1,  .8, .8 ]
    // 透明度列表
    let opaArray = [1,.8, .8]
    // 高度列表
    let indArray = [ 1, 0.8,  0.8]
    // 当前位置列表
    let curPosArray =   [ 280,120,420]
    // 当前缩放列表
    let curScaArray = []
    // 当前透明度列表
    let curOpaArray = []
    // 当前高度列表
    let curIndArray = []
    let left = 0
     
     
    // 是否可点击,控制点击频率
    let canClick = true
     
    // px和rpx转换比例,用于横向滑动的时候计算滑动距离(rpx)
    let screenRate = 1
     
    Page({
     
        data: {
            imgArray: [{
                image:'imgs/image1.png',
                text:'页面1'
            },{
                image:'imgs/image2.png',
                text:'页面2'
            },{
                image:'imgs/image3.png',
                text:'页面3'
            }],
            animation: [],
            indexArray: [2,1,1]
        },
        /**
         * 生命周期函数--监听页面加载
         */
        onLoad: function(options) {
            wx.getSystemInfo({
                success: (res) => {
                    screenRate = 750 / res.screenWidth
                }
            })
            this.animation = []
            for (let i = 0; i < 3; i++) {
                let animation = wx.createAnimation({
                    duration: 500,
                    timingFunction: 'ease-out',
                })
                this.animation.push(animation)
            }
        },
        touchstart(e) {
            left = e.touches[0].pageX
        },
     
        touchmove(e) {
            if (this.isMove) {
                return
            }
            let moveLength = (e.touches[0].pageX - left) * screenRate
            moveLength = moveLength > 60 ? 60 : moveLength
            moveLength = moveLength < -60 ? -60 : moveLength
            let rate = moveLength / 60
            if (rate == 1) { //从右往左滑
                this.isMove = true
                this.tapLeft()
            } else if (rate == -1) { //从左往右滑
                this.isMove = true
                this.tapRight()
            }
        },
     
        touchend(e) {
            setTimeout(()=>{
                this.isMove = false
            },500)
        },
     
        // 往左移
        tapLeft() {
            if (!canClick) {
                return
            }
            canClick = false
            setTimeout(() => {
                canClick = true
            }, 500)
            curPosArray = this.rollRight(posArray, 1)
            curScaArray = this.rollRight(scaArray, 1)
            curOpaArray = this.rollRight(opaArray, 1)
            curIndArray = this.rollRight(indArray, 1)
            let animation = this.data.animation
            for (let j = 0; j < 3; j++) {
                this.animation[j].scale(curScaArray[j], curScaArray[j]).left(curPosArray[j] + 'rpx').opacity(curOpaArray[j]).step()
                animation[j] = this.animation[j].export()
            }
            this.setData({
                animation: animation,
                indexArray: curIndArray
            })
        },
     
        tapRight() {
            if (!canClick) {
                return
            }
            canClick = false
            setTimeout(() => {
                canClick = true
            }, 500)
            curPosArray = this.rollLeft(posArray, 1)
            curScaArray = this.rollLeft(scaArray, 1)
            curOpaArray = this.rollLeft(opaArray, 1)
            curIndArray = this.rollLeft(indArray, 1)
            let animation = this.data.animation
            for (let j = 0; j < 3; j++) {
                this.animation[j].scale(curScaArray[j], curScaArray[j]).left(curPosArray[j] + 'rpx').opacity(curOpaArray[j]).step()
                animation[j] = this.animation[j].export()
            }
            this.setData({
                animation: animation,
                indexArray: curIndArray
            })
        },
     
        rollLeft: function(array, times) {
            for (let time = 0; time < times; time++) {
                let length = array.length - 1
                let temp = array[0]
                for (let i = 0; i < length; i++) {
                    array[i] = array[i + 1]
                }
                array[length] = temp
            }
            return array.concat()
        },
     
        rollRight: function(array, times) {
            for (let time = 0; time < times; time++) {
                let length = array.length - 1
                let temp = array[length]
                for (let i = length; i > 0; i--) {
                    array[i] = array[i - 1]
                }
                array[0] = temp
            }
            return array.concat()
        },
    })
    

    1.2. 方案二

    在这里插入图片描述

    1.2.1. banner.wxml

    <view class="swiper-body" bindtouchmove="tauchMove" bindtouchstart="tauchStart" bindtouchend="tauchEnd">
     <view class=".swiper-item-box {{item.zIndex==1?'none':''}}" wx:for="{{swiperList}}" wx:key="index" style="--index:{{item.zIndex}};--left:{{item.mLeft}}">
       <view class="swiper-item">
         <image src="{{item.url}}" mode="aspectFill" wx:if="{{item.type=='image'}}"></image>
         <view class="photo-item-layout">
           <view class="photo-item-title">标题</view>
           <view class="photo-item-label">标签 </view>
         </view>
       </view>
     </view>
    </view>
    

    1.2.3. banner.wxss

    page {
     background-color: #fff;
    }
    .swiper-body {
     height: 420rpx;
     position: relative;
     max-width: 750rpx;
     overflow: hidden;
     box-sizing: border-box;
     margin-top: 90rpx;
    }
    
    .swiper-item-box {
     position: absolute;
     width: 300rpx;
     height: 380rpx;
     top: 0;
     bottom: 0;
     left: 50%;
     margin: auto;
     transition: all 0.2s ease-in 0s;
     opacity: 1;
     box-shadow: 0px 13rpx 12rpx rgba(0, 0, 0, .5);
     border-radius: 15rpx;
     overflow: hidden;
     transform: scale(calc(0.5 + var(--index) / 10));
     margin-left: calc(var(--left) * 100rpx - 150rpx);
     z-index: var(--index);
    }
    
    .swiper-item-box.none {
     opacity: 0;
    }
    
    .swiper-item {
     overflow: hidden;
     position: relative;
     width: 100%;
     height: 100%;
     border-radius: 6rpx;
    }
    
    .swiper-item image{
     width: 100%;
     display: block;
     height: 100%;
     margin: 0;
     pointer-events: none;
    }
    
    image {
     max-width: 100%;
     display: inline-block;
     position: relative;
     z-index: 0;
    }
    
    
    
    .photo-item-layout {
     position: absolute;
     width: 100%;
     left: 0;
     bottom: 0;
     color: #fff;
     border-bottom-right-radius: 18rpx;
     float: left;
     display: flex;
     flex-direction: column;
     background: linear-gradient(180deg,  #0092fb00,#3691FB );
    }
    
    .photo-item-title {
     color: white;
     font-size: 32rpx;
     font-weight: 800;
     margin-top: 20rpx;
     text-align: center;
     overflow: hidden;
     text-overflow: -o-ellipsis-lastline;
     text-overflow: ellipsis;
     display: -webkit-box;
     -webkit-line-clamp: 1;
     -webkit-box-orient: vertical;
    }
    
    .photo-item-label {
     color: rgba(255, 255, 255, 0.829);
     font-size: 28rpx;
     text-align: center;
     padding: 3rpx 20rpx 10rpx 20rpx;
     border-top-right-radius: 20rpx;
     border-bottom-right-radius: 20rpx;
     overflow: hidden;
     text-overflow: -o-ellipsis-lastline;
     text-overflow: ellipsis;
     display: -webkit-box;
     -webkit-line-clamp: 1;
     -webkit-box-orient: vertical;
    }
    

    1.2.3. banner.js

    
    Page({
    
     data: {
       swiperList: [
         {
           type: 'image',
           url: '/img_fj.png'
         }, {
    
           type: 'image',
           url: '/img_banner_random.png',
         }, {
           type: 'image',
           url: '/img_activity.png'
         }, {
           type: 'image',
           url: '/img_activity.png'
         },
         {
           type: 'image',
           url: '/img_stage.png'
         },
         {
           type: 'image',
           url: '/img_activity.png'
         },
       ],
     },
    
    
     onLoad: function (options) {
       this.tauchSwiper('swiperList');
     },
    
    
     onShow: function () {
    
     },
     // 初始化tauchSwiper
     tauchSwiper(name) {
       let list = this.data[name];
       for (let i = 0; i < list.length; i++) {
         // Math.abs(x) 函数返回指定数字 “x“ 的绝对值
         list[i].zIndex = parseInt(list.length / 2) + 1 - Math.abs(i - parseInt(list.length / 2))
         list[i].mLeft = i - parseInt(list.length / 2)
       }
       this.setData({
         swiperList: list
       })
     },
     // tauchSwiper触摸开始
     tauchStart(e) {
       this.setData({
         tauchStart: e.touches[0].pageX
       })
     },
     // tauchSwiper计算方向
     tauchMove(e) {
       this.setData({
         direction: e.touches[0].pageX - this.data.tauchStart > 0 ? 'right' : 'left'
       })
     },
     // tauchSwiper计算滚动
     tauchEnd(e) {
       let direction = this.data.direction;
       let list = this.data.swiperList;
       if (direction == 'right') {
         let mLeft = list[0].mLeft;
         let zIndex = list[0].zIndex;
         for (let i = 1; i < list.length; i++) {
           list[i - 1].mLeft = list[i].mLeft
           list[i - 1].zIndex = list[i].zIndex
         }
         list[list.length - 1].mLeft = mLeft;
         list[list.length - 1].zIndex = zIndex;
         this.setData({
           swiperList: list
         })
       } else {
         let mLeft = list[list.length - 1].mLeft;
         let zIndex = list[list.length - 1].zIndex;
         for (let i = list.length - 1; i > 0; i--) {
           list[i].mLeft = list[i - 1].mLeft
           list[i].zIndex = list[i - 1].zIndex
         }
         list[0].mLeft = mLeft;
         list[0].zIndex = zIndex;
         this.setData({
           swiperList: list
         })
       }
     }
    })
    

    1.3. 方案三

    在这里插入图片描述

    1.3.1. banner.wxml

    <view class="pageLayout">
      <swiper indicator-dots='true' autoplay='true' interval='5000' duration='1000' circular='true'>
        <block wx:for="{{bnrUrl}}" wx:for-index="index">
          <swiper-item id='{{index}}' bindtap='bannerClick' data-bannertitle='{{item.title}}' data-bannerid='{{item.id}}'>
            <image class='bannerLayout' src='{{item.url}}' mode='scaleToFill'></image>
          </swiper-item>
        </block>
      </swiper>
    </view>
    

    1.3.2. banner.wxss

    /* 页面样式 */
    .pageLayout {
          background-size: 100%;
          padding: 0 30rpx 50rpx;
    }
    
    /* 轮播图 */
    .bannerLayout {
          width: 100%;
          height: 310rpx;
          box-sizing: border-box;
          overflow: hidden;
          border-radius: 20rpx;
          margin-top: 30rpx;
          margin-bottom: 24rpx;
          box-shadow: 0 0 10rpx #7d7d7d;
          background: #fff;
    }
    
    
    

    1.3.3. banner.js

    // pages/banner2/banner2.js
    const utils = require('../../utils/util.js');
    Page({
    
          /**
           * 页面的初始数据
           */
          data: {
                "bnrUrl": [{
                      "url": `weChatFile/icon_menu_yxt.png`,
                      "title": `标题一`
                }, {
                      "url": `weChatFile/icon_menu_yxt.png`,
                      "title": `标题二 `
                }]
          },
          
    
          /**
           * 生命周期函数--监听页面加载
           */
          onLoad: function (options) {
                let that = this
                that.getslideImg()
          },
          bannerClick: function (e) {
                var bannerId = e.currentTarget.dataset.bannerid;
                wx.navigateTo({
                      //方法一
                      url: '../bannerDetail/bannerDetail?bannerId='+bannerId,
                      //方法二
                      //url: `../bannerDetail/bannerDetail?bannerId=${bannerId}`,
                })
    
          },
          getslideImg: function () {
                let that = this
                // utils.getPostData('a/msmallapp/appWheel/list', function (res) {
                //       let resData = res.data
                //       console.log("===3==" + resData);
                //       console.log(resData);
                //       if (resData) {
                //             if (resData.success) {
                //                   let resList = resData.body.list
                //                   that.setData({
                //                         bnrUrl: resList
                //                   })
                //             }
                //       }
                // })
          },
          /**
           * 生命周期函数--监听页面初次渲染完成
           */
          onReady: function () {
    
          },
    
          /**
           * 生命周期函数--监听页面显示
           */
          onShow: function () {
    
          },
    
          /**
           * 生命周期函数--监听页面隐藏
           */
          onHide: function () {
    
          },
    
          /**
           * 生命周期函数--监听页面卸载
           */
          onUnload: function () {
    
          },
    
          /**
           * 页面相关事件处理函数--监听用户下拉动作
           */
          onPullDownRefresh: function () {
    
          },
    
          /**
           * 页面上拉触底事件的处理函数
           */
          onReachBottom: function () {
    
          },
    
          /**
           * 用户点击右上角分享
           */
          onShareAppMessage: function () {
    
          }
    })
    

    1.4. 方案四

    在这里插入图片描述

    1.4.1. banner.wxml

    <!--index.wxml-->
    <view class="container">
      <!-- 轮播图 -->
      <view class="banner-swiper">
        <swiper indicator-dots="{{indicator}}" autoplay="{{autoplay}}" current='{{swiperCurrent}}' indicator-color="{{beforeColor}}" indicator-active-color="{{afterColor}}" circular='{{circular}}' previous-margin="{{previousmargin}}" next-margin="{{nextmargin}}"
          bindchange="swiperChange">
          <block wx:for="{{arr}}" wx:key="key">
            <swiper-item>
              <image src="{{item.images}}" class="slide-image {{index == swiperCurrent ? ' active' : ''}}"></image>
              <view class='goods-info'>{{item.title}}</view>
              <view class='goods-more'>
                <view>
                  <text class='prefix'>免费样品</text>
                  <text class='nums'>({{item.num}})</text>
                </view>
                <view>
                  <text class='prefix supply'>供应价:</text>
                  <text class='price'>{{item.price}}</text>
                </view>
              </view>
            </swiper-item>
          </block>
        </swiper>
        <view class="dots">
          <block wx:for="{{arr}}" wx:key="{{index}}">
            <view class="{{index== cur?'active':''}} dot"></view>
          </block>
        </view>
      </view>
    </view>
    
    

    1.4.2. banner.wxss

    /**index.wxss**/
    /* 轮播图 */
    .banner-swiper{
      width: 100%;
      height: 540rpx;
      overflow: hidden;
      position: relative;
      background-color: #fff;
    } 
    
    swiper {
      display: block;
      height: 540rpx;
      font-size: 0;
    }
    
    .slide-image{
      width: 96%;
      display: block;
      margin: 0 auto;
      height: 410rpx;
      border-radius: 10rpx;
      font-weight: bold;
    } 
    
    .goods-info{
      font-size: 28rpx;
      color: #000;
      text-align: center;
      margin-top: 20rpx;
      margin-bottom: 20rpx;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
    .goods-more {
      display: flex;
      flex-direction: row;
      justify-content: center;
    }
    .supply {
      margin-left: 40rpx;
    }
    .prefix {
      font-size: 24rpx;
      color: #000;
    }
    
    .nums {
      font-size: 24rpx;
      color: #666;
    }
    
    .price {
      font-size: 24rpx;
      color: #fc515c;
    }
    .dots{  
        position: absolute;
        right: 0;
        bottom: 140rpx;
        left: 0;
        width: 300rpx;
        height: 18rpx;
        margin: 0 auto;
        text-align: center;
        display: flex;
        flex-direction: row;
        justify-content: center;
    }  
    /*未选中时的小圆点样式 */
    .dot{ 
        width: 10rpx;
        height: 10rpx; 
        margin-right: 8rpx;
        border-radius: 100rpx;
        background-color: #f2f2f2;
    }  
    /*选中以后的小圆点样式  */
    .active{
        width: 36rpx;
        height: 10rpx; 
        border-radius: 5rpx; 
        background-color: #f2f2f2;
    }
    

    1.4.3. banner.js

    //index.js
    //获取应用实例
    const app = getApp()
    
    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        arr: [{
          images: '/weChatFile/img_fj.png',
          title: 'Lumea Prestige系列脱毛装置',
          num: '2',
          price: '99.00'
        },
        {
          images: '/weChatFile/img_banner_random.png',
          title: 'Lumea Prestige系列脱毛装置',
          num: '2',
          price: '99.00'
        },
        {
          images: '/weChatFile/img_activity.png',
          title: 'Lumea Prestige系列脱毛装置',
          num: '2',
          price: '99.00'
        }],
        beforeColor: "white",//指示点颜色 
        afterColor: "coral",//当前选中的指示点颜色 
        previousmargin: '24px',//前边距
        nextmargin: '24px',//后边距
        indicator: false, //是否显示指示点
        interval: 5000,  //自动切换时间间隔
        duration: 400,  //滑动动画时长
        autoplay: true, //是否自动切换
        circular: true, //是否采用衔接滑动
        cur: 0,         //当前所在滑块的index
      },
    
      //轮播图的切换事件  
      swiperChange(e) {
        let cur = e.detail.current  //获取当前轮播图片的下标, 可以给当前指示点加样式
        this.setData({
          cur: cur
        })
      },
      
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        
      },
    
      /**
       * 生命周期函数--监听页面初次渲染完成
       */
      onReady: function () {
        
      },
    
      /**
       * 生命周期函数--监听页面显示
       */
      onShow: function () {
        
      },
    
      /**
       * 生命周期函数--监听页面隐藏
       */
      onHide: function () {
        
      },
    
      /**
       * 生命周期函数--监听页面卸载
       */
      onUnload: function () {
        
      },
    
      /**
       * 页面相关事件处理函数--监听用户下拉动作
       */
      onPullDownRefresh: function () {
        
      },
    
      /**
       * 页面上拉触底事件的处理函数
       */
      onReachBottom: function () {
        
      },
    
      /**
       * 用户点击右上角分享
       */
      onShareAppMessage: function () {
        
      }
    })
    
  • 相关阅读:
    Redisson实现分布式锁
    【APP自动化测试必知必会】Appium之微信小程序自动化测试
    二分查找一看就会,一写就废?
    【MyBatis Plus】深入探索 MyBatis Plus 的条件构造器,自定义 SQL语句,Service 接口的实现
    广东建筑覆膜板厂家
    MarkdownPad2, CSDN及有道云笔记对数学公式的支持
    C++面试八股文:如何避免死锁?
    Spring Boot 异步线程静态获取request对象为空 RequestContextHolder 为空 Java 异步线程获取request为空
    刷题记录:牛客NC211219电话网络
    牛客刷SQL
  • 原文地址:https://blog.csdn.net/qq_36158551/article/details/139370842