微信小程序 自定义模态框 Modal 淡入淡出动画效果 Fade-in Fade-out

WXML

<!-- 自定义模态框 -->
<view bindtap='fadeInDlg'  style='display:flex;justify-content: center;'><text>点击</text></view>
<view class="mask" bindtap='fadeOutDlg' animation="{{animationBgData}}" catchtouchmove="preventTouchMove" wx:if="{{showModalDlg}}"></view>
<view class="modalDlg" animation="{{animationData}}" wx:if="{{showModalDlg}}">
    <text>获取授权</text>
    <text>检测到您未授权小程序获取您的用户信息,是否重新授权?</text>
    <view>
    <button bindtap="modelCancel">取消</button>
    <button bindtap="modelC">确定</button>
    </view>
</view>

WXSS

.mask{
    width: 100%;
    height: 100%;
    position: fixed;
    top: 0;
    left: 0;
    background: #000;
    z-index: 9000;
    opacity: 0;
}
.modalDlg{
    width: 580rpx;
    height: 400rpx;
    position: fixed;
    top: 60%;
    left: 0;
    z-index: 9999;
    margin: -370rpx 85rpx;
    background-color: #fff;
    border-radius: 10rpx;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    overflow: hidden;
    
}
.modalDlg>text{
  font-size:30rpx;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
.modalDlg>text:first-child{
  height:80rpx;
  font-weight: 700;
  width:100%;
  border-bottom: 1rpx solid #CCC;
}
.modalDlg>text:nth-child(2){
  height:100rpx;
  margin:0 40rpx;
}
.modalDlg>view{
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
.modalDlg>view>button{
  width:290rpx;
  height:80rpx;
  font-size: 30rpx;
  border-radius: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  border-top: 1rpx solid #CCC;
}
.modalDlg>view>button:first-child{
  border-right:1rpx solid #CCC;
}
.modalDlg>view>button::after {
  border-radius: 0;
}

JS

Page({

  data: {
    showModalDlg: false
  },
  onLoad: function() {

  },
  fadeInDlg:function(){
    this.setData({
      showModalDlg:true
    })

    var animation = wx.createAnimation({
      duration:0,
      timingFunction:'step-start',
    })
    animation.opacity(0).scale(0.8,0.8).step();
    this.setData({
      animationData: animation.export()
    })
    animation = wx.createAnimation({
      duration: 200,
      timingFunction: 'ease',
    })
    animation.opacity(1).scale(1,1).step()
    this.setData({
      animationData:animation.export()
    })

    var animationBg = wx.createAnimation({
      duration: 200,
      timingFunction: 'step-start',
    })
    animationBg.opacity(0).step()
    animationBg = wx.createAnimation({
      duration:500,
      timingFunction:'ease',
    })
    animationBg.opacity(0.5).step()
    this.setData({
      animationBgData:animationBg.export()
    })
  },
  fadeOutDlg:function(){
    var _this = this
    var animation = wx.createAnimation({
      duration:200,
      timingFunction:'ease',
    })
    animation.opacity(0).scale(0.8, 0.8).step();
    this.setData({
      animationData:animation.export()
    })

    var animationBg = wx.createAnimation({
      duration: 200,
      timingFunction: 'ease',
    })
    animationBg.opacity(0).step()
    this.setData({
      animationBgData: animationBg.export()
    })

    setTimeout(function(){
      this.setData({
        showModalDlg: false
      })
    }.bind(this),200)
  },

  preventTouchMove: function() {
    //阻止触摸
  },

})

 

微信小程序 自定义模态框,带 Button 组件的 Model 框

WXML

<!-- 自定义模态框 -->
<view class="mask" bindtap='modelCancel' catchtouchmove="preventTouchMove" wx:if="{{showModalDlg}}"></view>
<view class="modalDlg" wx:if="{{showModalDlg}}">
    <text>获取授权</text>
    <text>检测到您未授权小程序获取您的用户信息(头像/昵称),是否重新授权?
    请依次点击 授权->登录</text>
    <view>
    <button open-type="openSetting">授权</button>
    <button bindtap="toLogin">登录</button>
    </view>
</view>

WXSS

.mask{
    width: 100%;
    height: 100%;
    position: fixed;
    top: 0;
    left: 0;
    background: #000;
    z-index: 9000;
    opacity: 0.7;
}

.modalDlg{
    width: 580rpx;
    height: 400rpx;
    position: fixed;
    top: 60%;
    left: 0;
    z-index: 9999;
    margin: -370rpx 85rpx;
    background-color: #fff;
    border-radius: 10rpx;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    overflow: hidden;
    
}
.modalDlg>text{
  font-size:30rpx;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
.modalDlg>text:first-child{
  height:80rpx;
  font-weight: 700;
  width:100%;
  border-bottom: 1rpx solid #CCC;
}
.modalDlg>text:nth-child(2){
  height:100rpx;
  margin:0 40rpx;
}

.modalDlg>view{
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}

.modalDlg>view>button{
  width:290rpx;
  height:80rpx;
  font-size: 30rpx;
  border-radius: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  border-top: 1rpx solid #CCC;
}
.modalDlg>view>button:first-child{
  border-right:1rpx solid #CCC;
}
.modalDlg>view>button::after {
  border-radius: 0;
}

JS

Page({

  data: {
    showModalDlg: true
  },

  preventTouchMove: function () {
    //阻止触摸
  },

  modelCancel:function(){
    this.setData({
      showModalDlg: false
    })
  },
})

 

微信小程序 图片使用 binderror 替换错误图片在 for 循环时发生数量的错误

测试产品列表时发现,在模拟器上使用列表筛选功能,能够正确显示列表个数,但在手机端个数显示多了,经排查是因为 img 标签使用了 binderror 功能,图片显示错误时调用了替代图片。

使用筛选功能后,产品列表的数量由 12 减少至 6,但之前 binderror 并未全部全部替换,特别是当 img 标签启用了 lazy-load='true' 功能,导致上一次列表的 binderror 继续执行

解决方法,插入图片时判断新列表时候有新列表的 key 存在,存在再替换默认图片 arr.hasOwnProperty()

errorFunction: function(event) {
   console.log('errorFunction')
   console.log(event)
   var index = event.currentTarget.dataset.index
   console.log(index)
   var img = 'rlist[' + index + '].DefaultPicUrl_s'

   if (this.data.rlist.hasOwnProperty(index)) {
     this.setData({
       [img]: this.data.img_error
     })
   }
 },

 

微信小程序 解决自定义弹出层滑动时下层页面滚动问题

WXML

将整个底层页面使用 scroll-view 包裹起来,设置 scroll-y 当显示弹出层的时候为 true, 闭关弹出层的时候为 false

<scroll-view scroll-y="{{showModalStatus?'true':'false'}}">

</scroll-view>
WXSS

Page 设置为绝对定位,宽高各百分之百 , scroll-view 高度 百分之百

Page{
  position: absolute;
  width: 100%;
  height: 100%;
  display: block;
  background: #FAFAFA;
  overflow-y: hidden;
}
scroll-view{
  height:100%;
}
JS

JS 控制 showModalStatus 的开关。

 

不过这引入了新的问题,无法触发 onReachBottom  页面上拉触底事件的处理函数

不介意的话可以使用 scroll-view 的 bindscrolltolower 进行解决 bindscrolltolower 方法触发 onReachBottom()

WXML

<scroll-view bindscrolltolower='bindscrolltolower' scroll-y="{{showModalStatus?'true':'false'}}"> 

</scroll-view>

JS

bindscrolltolower:function(){
  console.log('bindscrolltolower')
  var page = getCurrentPages().pop()
  console.log(page)
  page.onReachBottom()
}

所以另一种方法

WXML

把底层页面使用 view 包裹起来,动态设置样式

<view class="{{showModalStatus?'page-fix':''}}">

</view>
WXSS

动态样式开启模态层时,绝对定位

.page-fix{
  position: fixed;
}

 

微信小程序 文章加载占位样式 CSS Placeholder

类似豆瓣 APP 动画闪烁效果

WXML:

<view class="text-loading">
  <view class='pic-loading-line'></view>
  <view class='text-loading-line-first'>
    <view class='text-loading-line'></view>
    <view class='text-loading-line'></view>
    <view class='text-loading-line'></view>
  </view>
  <view class='text-loading-line-second'>
    <view class='text-loading-line'></view>
    <view class='text-loading-line'></view>
    <view class='text-loading-line'></view>
  </view>
</view>

WXSS:

.text-loading {
  width: 90%;
  margin:50rpx;
  /* border:1rpx solid #ccc; */
}

.text-loading .pic-loading-line {
  display: inline-block;
  width: 130rpx;
  height: 130rpx;
  margin-right: 20rpx;
  margin-bottom: 20rpx;
  animation: pulse 1s infinite ease-in-out;
}

.text-loading .text-loading-line-first {
  display: inline-block;
  width: 70%;
  height: 150rpx;
}

.text-loading .text-loading-line-second {
  display: inline-block;
  width: 100%;
  height: 150rpx;
}

.text-loading-line {
  height: 30rpx;
  margin-bottom: 20rpx;  
  width: 100%;
  animation: pulse 1s infinite ease-in-out;
}

.text-loading-line:nth-child(1) {
  width: 100%;
}

.text-loading-line:nth-child(2) {
  width: 90%;
}

.text-loading-line:nth-child(3) {
  width: 50%;
}

@keyframes pulse {
  0% {
    background-color: rgba(165, 165, 165, 0.1);
  }

  50% {
    background-color: rgba(165, 165, 165, 0.3);
  }

  100% {
    background-color: rgba(165, 165, 165, 0.1);
  }
}

 

微信小程序 重写 Radio CheckBox 样式 美化单选框复选框

单选按钮 Radio

wxss:

/*  重写 radio 样式  */
/* 未选中的 背景样式 */
radio .wx-radio-input{
   border-radius: 50%;/* 圆角 */
   width: 40rpx;
   height: 40rpx;
}
/* 选中后的 背景样式 (红色背景 无边框 可根据UI需求自己修改) */
radio .wx-radio-input.wx-radio-input-checked{
   border: none;
   background: red;
}
/* 选中后的 对勾样式 (白色对勾 可根据UI需求自己修改) */
radio .wx-radio-input.wx-radio-input-checked::before{
   border-radius: 50%;/* 圆角 */
   width: 40rpx; /* 选中后对勾大小,不要超过背景的尺寸 */
   height: 40rpx; /* 选中后对勾大小,不要超过背景的尺寸 */
   line-height: 40rpx;
   text-align: center;
   font-size:30rpx; /* 对勾大小 30rpx */
   color:#fff; /* 对勾颜色 白色 */
   background: transparent;
   transform:translate(-50%, -50%) scale(1);
   -webkit-transform:translate(-50%, -50%) scale(1);
}
复选按钮 Checkbox

wxss:

/*  重写 checkbox 样式  */
/* 未选中的 背景样式 */
checkbox .wx-checkbox-input{
   border-radius: 50%;/* 圆角 */
   width: 40rpx; /* 背景的宽 */
   height: 40rpx; /* 背景的高 */
}
/* 选中后的 背景样式 (红色背景 无边框 可根据UI需求自己修改) */
checkbox .wx-checkbox-input.wx-checkbox-input-checked{
   border: none;
   background: red;
}
/* 选中后的 对勾样式 (白色对勾 可根据UI需求自己修改) */
checkbox .wx-checkbox-input.wx-checkbox-input-checked::before{
   border-radius: 50%;/* 圆角 */
   width: 40rpx;/* 选中后对勾大小,不要超过背景的尺寸 */
   height: 40rpx;/* 选中后对勾大小,不要超过背景的尺寸 */
   line-height: 40rpx;
   text-align: center;
   font-size:30rpx; /* 对勾大小 30rpx */
   color:#fff; /* 对勾颜色 白色 */
   background: transparent;
   transform:translate(-50%, -50%) scale(1);
   -webkit-transform:translate(-50%, -50%) scale(1);
}

 

微信小程序 JavaScript 时间比较函数 JS 日期比较

// 时间比较函数
compareDate:function (startDate, endDate) {
  var arrStart = startDate.split("-");
  var startTime = new Date(arrStart[0], arrStart[1], arrStart[2]);
  var startTimes = startTime.getTime();
  var arrEnd = endDate.split("-");
  var endTime = new Date(arrEnd[0], arrEnd[1], arrEnd[2]);
  var endTimes = endTime.getTime();
  if(endTimes<startTimes) {
    return false;
  }
return true;
},

 

微信小程序实现点击滑动展开效果动画

js

let animationShowHeight = 300;
Page({
  /**
   * 页面的初始数据
   */
  data: {
    animation: ''
  },
  // 下来
  btnClick: function () {
    var animation = wx.createAnimation({
      transformOrigin: "50% 50%",
      duration: 1000,
      timingFunction: "ease",
      delay: 0
    })
    this.animation = animation
    animation.translateY(animationShowHeight).step()
    this.setData({
      animation: animation.export(),
    })
  },
  // 上去
  btnClickTo: function () {
    var animation = wx.createAnimation({
      transformOrigin: "50% 50%",
      duration: 1000,
      timingFunction: "ease",
      delay: 0
    })
    this.animation = animation
    animation.translateY(0).step()
    this.setData({
      animation: animation.export(),
    })
  }  
})

wxml

<button type="primary" bindtap="btnClick"> 点我下去 </button>
<button type="primary" bindtap="btnClickTo"> 点我回去 </button>
<view class="body-view" animation="{{animation}}">
  <view>我一会就出来吓死你</view>
  <view>我一会就出来吓死你</view>
  <view>我一会就出来吓死你</view>
</view>

微信小程序 picker 组件,当  range 为 Object Array 类型时示例代码

微信小程序 picker 组件,当  range 为 Object Array 类型时

wxml:

<picker bindchange="bindPickerChange" value="{{index}}" range-key="name" range="{{objectArray}}">
    <view class="picker">
      当前选择:{{objectArray[index].name}}
    </view>
</picker>

js:

Page({
  data: {
    objectArray: [
      {
        id: 0,
        name: '美国'
      },
      {
        id: 1,
        name: '中国'
      },
      {
        id: 2,
        name: '巴西'
      },
      {
        id: 3,
        name: '日本'
      }
    ]
  },
  bindPickerChange: function(e) {
    console.log('picker发送选择改变,携带值为', e.detail.value)
    var index = e.detail.value;
    var currentId = this.data.objectArray[index].id; 
    this.setData({
      index: e.detail.value
    })
  }
})