欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

wxs微信小程序轮播图——高度自适应并动态过渡变化

程序员文章站 2022-06-25 11:57:30
之前实现了基于原生js的高度自适应且动态平滑过渡的轮播图:由于项目需要 将这一交互动效同步进了微信小程序...

之前实现了基于原生js的高度自适应且动态平滑过渡的轮播图:
原生js实现一个高度自适应且动态平滑变高的轮播图

由于项目需要 将这一交互动效在微信小程序里做了实现 结合了微信小程序wxs的脚本语言 下面是效果图:
wxs微信小程序轮播图——高度自适应并动态过渡变化

使用脚本语言wxs的原因

实现动态的高度渲染需要监听微信小程序swiper组件bindtransition属性的参数dx(即轮播块在x轴方向上的位移值)并动态地反映到y轴方向上的高度上。 这在基本的js逻辑文件中做实现时 需要频繁调用setData方法把计算得到的高度值渲染为轮播区域的高度 而
wxs微信小程序轮播图——高度自适应并动态过渡变化
这样的方式会带来严重的性能问题 所以需要使用在视图层表现优秀的wxs脚本来实现

关于wxs脚本语言的介绍 详见 微信官网文档——wxs

这里只结合项目和交互实现叙述用到的wxs相关处理方式

代码实现

下面是动效实现的代码 注释部分有实现思路的叙述和对wxs的一些基本使用方式

.wxml:(项目需求提出在轮播区域加入视频的展示 所以出现了video类型的轮播块)

	  <!-- wxs脚本的引入 相对路径 -->
      <wxs src="./swiperHT.wxs" module="swiperHT"/>

      <!-- 变高轮播 视频加入 -->
      <view style="position:relative;">
        <!-- ******绑定了三个属性 bindchange监听轮播块的变化以记录当前轮播快序号 并把"轮播块发生改变"这一状态记录为变量indexChange的值为true
        bindanimationfinish监听轮播动画结束 还原indexChange的值为false以便区分是否触发了轮播块的改变--改变时需要过渡渲染到新高度 否则过渡回旧高度
        bindtransition即对 "接触轮播区域后手势划动" 的整个过程的监听是一个复杂的过程 放进wxs中        
         -->
        <!-- swiper组件的bindtransition方法可以调用声明过的wxs模块swiperHT中的方法bt 通过data-的形式向方法中传值 
        ic:是否发生轮播块的改变  cw:屏幕宽度  list:数据数组  index:当前轮播块序号-->
        
        <swiper id="swiperOut" style="height:{{nowH}}px" duration="{{duration}}" 
        data-ic="{{indexChange}}" data-cw="{{clientW}}" data-list="{{imgSwiperList}}" data-index="{{durationIndex}}" 
        bindtransition="{{swiperHT.bt}}" bindchange="change" bindanimationfinish="changeEnd">
          <!-- 需要的数据格式为(url 宽 高三项必填):[{url:"",height:100;width:100;type:pic},{...},{...},...] -->
          <swiper-item wx:for="{{imgSwiperList}}" wx:key="index" >
            <!-- 视频轮播块 -->
            <view class="swiperInVP" wx:if="{{item.type==='video'}}">
              <video 
                wx:if="{{item.type==='video'&&durationIndex===index}}"
                style="width:100%;height:100%;"
                src="{{item.url}}" 
                controls
                autoplay="{{true}}"
              ></video>
            </view>
            <!-- 图片轮播块 -->
            <view class="swiperInVP" wx:if="{{item.type==='pic'}}" 
            style="background-image: url({{item.url+'?imageslim'}});"></view>
          </swiper-item>
        </swiper>
        <!-- 右下角数字提示 -->
        <view class="swiperNum">{{durationIndex+1}}/{{imgSwiperList.length}}</view>
      </view>

.wxss:

/* 顶部轮播 */
.swiperInVP{
  width:100%;height:100%;background-size:cover;background-position:center;
}
.swiperNum{
  position:absolute;
  right:16px;
  bottom:36px;
  background:rgba(0,0,0,0.3);
  border-radius:12px;
  color:white;
  padding:5px 8px;
  font-size:11px;
  line-height:11px;
}

.js:

  imgSwiperList: [],//顶部轮播图片列表(url 宽 高三项必填):  [{url:"",height:100;width:100;type:pic},{...},{...},...]
  duration: 180,//轮播区域过渡动画时长
  durationIndex: 0,//轮播区域轮播块index
  nowH:0,//初始轮播区域高度(第一个轮播块在当前屏宽下的高度)
  indexChange: false,//是否发生了轮播块的变动
  clientW:0,//当前页面宽度

  //swiper组件发生轮播块变动时触发的事件
  change: function (e) {
    console.log("index变动结束", e.detail.current);//触发于轮播块发生变动的时候
    this.setData({
      durationIndex: e.detail.current,//记录新的轮播块序号
      indexChange: true//发生了轮播块改变 需要过渡渲染新的高度
    })
  },
  //划动结束事件
  changeEnd: function (e) {
    console.log("一块轮播动画结束", e.detail.current);
    //触发于滑动动画结束的时候 有可能停留在当前块
    this.setData({
      indexChange: false//未发生轮播块改变 过渡回旧的高度
    })
  },

.wxs:

var swiperOut;
var swiperInVP;

var dataset;
var index;
var list;
var cw;
var ic;


//滑动过程中
var bt=function(e,ins){
  //******直接打印参数输出的是两个对象 需要转换成字符串后打印查看 
  // 观察可知第一个参数中能够取到wxs模块引用处的传值 第二个参数中暴露有方法可以进行dom的截取和操作 
  // console.log(JSON.stringify(e),"e")
  // console.log(JSON.stringify(ins),"ins")

  swiperOut=ins.selectComponent("#swiperOut")
  swiperInVP=ins.selectComponent(".swiperInVP")

  dataset =  e.instance.getDataset();
  index = dataset.index;
  list = dataset.list;
  cw = dataset.cw;
  ic = dataset.ic;

  if(e.detail.dx>0){
    // console.log("左划")
    if (index < list.length) {
      if (ic === false) {//未发生轮播块改变 过渡回旧的高度
        var nowH = (list[index].height) / (list[index].width) * cw; //当前轮播块高度
        if (index === list.length-1){
          var nextH = (list[index].height) / (list[index].width) * cw; //下一个轮播块高度
        }else{
          var nextH = (list[index + 1].height) / (list[index + 1].width) * cw; //下一个轮播块高度
        }
        var cs = (nextH - nowH) / cw * e.detail.dx 
        // console.log("落定前", "当前轮播快高度", nowH, "下个轮播块高度", nextH, "cs变动值", cs, "临界基准", ic)
        // console.log(nowH + cs)
        swiperOut.setStyle({//******通过样式设置的方式动态渲染高度 呈现高度变化的过渡过程 避免对setData()的频繁调用
          "height": nowH + cs + 'px'
        })
        swiperInVP.setStyle({
          "height": nowH + cs + 'px'
        })
      } else if (ic === true) {//发生了轮播块改变 需要过渡渲染新的高度
        var nowH = (list[index - 1].height) / (list[index - 1].width) * cw; //当前轮播块高度
        var nextH = (list[index].height) / (list[index].width) * cw; //下一个轮播块高度
        var cs = (nextH - nowH) / cw * e.detail.dx 
        // console.log("落定后", "当前轮播快高度", nowH, "下个轮播块高度", nextH, "cs变动值", cs, "临界基准", ic)
        // console.log(nowH + cs)
        swiperOut.setStyle({
          "height": nowH + cs + 'px'
        })
        swiperInVP.setStyle({
          "height": nowH + cs + 'px'
        })
      }
    }
  }else if(e.detail.dx<0){
    // console.log("右划")
    if (index >= 0) {
      if (ic === false) {//未发生轮播块改变 过渡回旧的高度
        var nowH = (list[index].height) / (list[index].width) * cw; //当前轮播块高度
        if (index === 0){
          var nextH = (list[index].height) / (list[index].width) * cw; //下一个轮播块高度
        }else{
          var nextH = (list[index - 1].height) / (list[index - 1].width) * cw; //下一个轮播块高度
        }
        var cs = (nextH - nowH) / cw * e.detail.dx 
        // console.log("右划落定前", "当前轮播快高度", nowH, "下个轮播块高度", nextH, "cs变动值", cs, "临界基准", ic)
        // console.log(nowH - cs)
        swiperOut.setStyle({//******通过样式设置的方式动态渲染高度 呈现高度变化的过渡过程 避免对setData()的频繁调用
          "height": nowH - cs + 'px'
        })
        swiperInVP.setStyle({
          "height": nowH - cs + 'px'
        })
      } else if (ic === true) {//发生了轮播块改变 需要过渡渲染新的高度
        var nowH = (list[index + 1].height) / (list[index + 1].width) * cw; //当前轮播块高度
        var nextH = (list[index].height) / (list[index].width) * cw; //下一个轮播块高度
        var cs = (nextH - nowH) / cw * e.detail.dx 
        // console.log("右话落定后", "当前轮播快高度", nowH, "下个轮播块高度", nextH, "cs变动值", cs, "临界基准", ic)
        // console.log(nowH - cs)
        swiperOut.setStyle({
          "height": nowH - cs + 'px'
        })
        swiperInVP.setStyle({
          "height": nowH - cs + 'px'
        })
      }
    }
  }
}

module.exports = { 
  bt:bt
};

本文地址:https://blog.csdn.net/mrl268/article/details/107870192