小程序swiper demo

小程序swiper demo

demo的性能太差,仅仅是提供思路,实际应用中需要优化
纯js实现swiper

方案1(需要优化性能、上下滚动)

swiper.js

function swiper(that) {
  that.handleStart = handleStart
  that.handleMove = handleMove
  that.handleEnd = handleEnd
}
/*
* @触摸起点
* @获取起点时间,起点坐标
*/
function handleStart(e){
  const { timeStamp } = e // 起点时间
  const { clientX, clientY } = e.touches[0] //起点坐标
  this.setData({ 
    touching: true,
    startX: clientX,
    startY: clientY,
    startTime: timeStamp
  })
}
/*
* @触摸变换
* @坐标轴
* X -> 右, X轴自左向右自增
* Y -> 下, Y轴自上向下自增
*
* @上下滑动(|Y| > |X|),终止计算
* @左右滑动(|Y| < |X|),终点X坐标 - 起点X坐标 > 0
* > 0;(页面向右滑动,偏移距离增大。偏移距离 = offsetOld + |X|)
* < 0;(页面向左滑动,偏移距离减小。偏移距离 = offsetOld - |X|)
*
*/
function handleMove(e){ // 坐标变换,触摸变换触发页面左右滑动
  const { clientX, clientY } = e.touches[0]
  let { startX, startY, offsetOld } = this.data
  let _X = clientX - startX,
      _Y = clientY - startY
  if(Math.abs(_X) <= Math.abs(_Y)) 
    return this.setData({ touching: false })
  else
    this.setData({ offset: offsetOld + _X })
}
/*
* @触摸结束
*
* @上下滑动(|Y| > |X|),终止计算
* @左右滑动(|Y| < |X|)
*
* @快速滑动: 时间最长小于300ms,最短距离50触发滑动事件  T < 300 && |X| >= 50
* @慢速滑动: T > 300 && |X| >= width/2
* index = 0 终止右移(X > 0),并复原move效果
* index = last 终止左移(X < 0),并复原move效果
*/
function handleEnd(e){ // 坐标变换终止
  const { timeStamp, target: { dataset: { index } } } = e // index 小圆点变换状态
  const { clientX, clientY } = e.changedTouches[0]
  let { list, startX, startY, startTime, width, offset, offsetOld } = this.data
  let T = timeStamp - startTime,
      _X = clientX - startX,
      _Y = clientY - startY,
      X = Math.abs(_X),
      Y = Math.abs(_Y)
  if(X < Y || T < 300 && X < 50 || T >= 300 && X < Math.round(width/2) || index == 0 && _X > 0 || index == list.length - 1 &&  _X < 0) {
    this.setData({
      offset: offsetOld
    })
  }else {
    // if(T <= 300) {
    //   this.setData({ duration: 300 })
    //   setTimeout(() => {
    //     this.setData({ duration: 0 })
    //   }, 300)
    // }
    if(_X < 0) width = -width
      this.setData({
        offset: offsetOld + width,
        offsetOld: offsetOld + width,
      })
  }

}
module.exports = swiper 

swiper.wxss

.page-swiper{
  width:100%;
  overflow-x:hidden;
}
.swiper-content{
  display:flex;
  min-height:100vh;
}
.swiper-content .content-slider{
  width:100vh;
  position: relative;
  top:0;
  left:0;
}
.swiper-content .content-slider:nth-child(odd){
  background-color:#f5f5f5;
}
.overflow-hidden{
  overflow:hidden;
}

index.js

const swiper = require('../../../../util/swiper')
Page({
  data: {
    list: [
      {
        page: '',
        title: '展览展览'
      },
      {
        page: '',
        title: 'VIP专区VIP专区'
      },
      {
        page: '',
        title: '购票购票购票'
      },
      {
        page: '',
        title: '动态动态动态'
      }
    ],
    touching: false, // 触摸后防止抖动
    duration: 600, // 延缓动画
    offsetOld: 0, // 保留距离状态 
    offset: 0, // 向左移动的距离 
    startX: 0, // X轴起点坐标
    startY: 0, // Y轴起点坐标
    startTime: 0, // 触摸起点时间
    width: 375 //默认屏幕宽度
  },
  /*
  * @获取设备宽度
  */
  onLoad() {
    const res = wx.getSystemInfoSync()
    this.setData({ width: res.windowWidth })
    swiper(this)
  },
})

index.wxml

<view class="page-swiper" bind:touchstart="handleStart" bind:touchmove="handleMove" bind:touchend="handleEnd">
  <view class="swiper-content {{touching?'overflow-hidden':''}}" style="width:{{width*list.length}}px;transform: translate3d({{offset ? offset : 0}}px, 0px, 0px);transition-duration: {{duration}}ms;">
    <view 
      class="content-slider" 
      wx:for-items="{{list}}" 
      wx:key="{{item}}" 
      data-index="{{index}}"
    >
    <scroll-view>
      {{item.title}}
    </scroll-view>
  </view>
  </view>
</view>

index.wxss

.page-swiper{
  width:100%;
  overflow-x:hidden;
}
.swiper-content{
  display:flex;
  min-height:100vh;
}
.swiper-content .content-slider{
  width:100vh;
  position: relative;
  top:0;
  left:0;
}
.swiper-content .content-slider:nth-child(odd){
  background-color:#f5f5f5;
}
.swiper-transform {
  transform: translate3d(0px, 0px, 0px);
  transition-duration: 0ms;
}

实现2(不推荐)

index.js

Page({
  data: {
    list: [
      {
        page: '',
        title: '展览展览'
      },
      {
        page: '',
        title: 'VIP专区VIP专区'
      },
      {
        page: '',
        title: '购票购票购票'
      },
      {
        page: '',
        title: '动态动态动态'
      }
    ],
    offsetOld: 0, // 保留距离状态 
    offset: 0, // 向左移动的距离 
    startX: 0, // X轴起点坐标
    startY: 0, // Y轴起点坐标
    startTime: 0, // 触摸起点时间
    width: 375 //默认屏幕宽度
  },
  /*
  * @获取设备宽度
  */
  onLoad() {
    const res = wx.getSystemInfoSync()
    this.setData({ width: res.windowWidth })
  },
  /*
  * @触摸起点
  * @获取起点时间,起点坐标
  */
  handleStart(e){
    const { timeStamp } = e // 起点时间
    const { clientX, clientY } = e.touches[0] //起点坐标
    this.setData({ 
      startX: clientX,
      startY: clientY,
      startTime: timeStamp
    })
  },
  /*
  * @触摸变换
  * @坐标轴
  * X -> 右, X轴自左向右自增
  * Y -> 下, Y轴自上向下自增
  *
  * @上下滑动(|Y| > |X|),终止计算
  * @左右滑动(|Y| < |X|),终点X坐标 - 起点X坐标 > 0
  * > 0;(页面向右滑动,偏移距离增大。偏移距离 = offsetOld + |X|)
  * < 0;(页面向左滑动,偏移距离减小。偏移距离 = offsetOld - |X|)
  *
  */
  handleMove(e){ // 坐标变换,触摸变换触发页面左右滑动
    const { clientX, clientY } = e.touches[0]
    let { startX, startY, offsetOld } = this.data
    let _X = clientX - startX,
        _Y = clientY - startY
    if(Math.abs(_X) <= Math.abs(_Y)) return
    this.setData({ offset: offsetOld + _X })
  },
  /*
  * @触摸结束
  *
  * @上下滑动(|Y| > |X|),终止计算
  * @左右滑动(|Y| < |X|)
  *
  * @快速滑动: 时间最长小于300ms,最短距离50触发滑动事件  T < 300 && |X| >= 50
  * @慢速滑动: T > 300 && |X| >= width/2
  * index = 0 终止右移(X > 0),并复原move效果
  * index = last 终止左移(X < 0),并复原move效果
  */
  handleEnd(e){ // 坐标变换终止
    const { timeStamp, target: { dataset: { index } } } = e // index 小圆点变换状态
    const { clientX, clientY } = e.changedTouches[0]
    let { list, startX, startY, startTime, width, offset, offsetOld } = this.data
    let T = timeStamp - startTime,
        _X = clientX - startX,
        _Y = clientY - startY,
        X = Math.abs(_X),
        Y = Math.abs(_Y)
    // if(X < Y) return
    if(X < Y || T < 300 && X < 50 || T >= 300 && X < Math.round(width/2) || index == 0 && _X > 0 || index == list.length - 1 &&  _X < 0) {
      this.setData({
        offset: offsetOld
      })
    }else {
      if(_X < 0) width = -width
        this.setData({
          offset: offsetOld + width,
          offsetOld: offsetOld + width,
        })
    }
  }
})

index.wxss

.page-swiper{
  width:100%;
  overflow-x:hidden;
}
.swiper-content{
  display:flex;
  min-height:100vh;
}
.swiper-content .content-slider{
  width:100vh;
  position: relative;
  top:0;
  left:0;
}
.swiper-content .content-slider:nth-child(odd){
  background-color:#f5f5f5;
}
.swiper-transform {
  transition: all 100ms ease;
  -webkit-transform: translate3d(0, 0, 0);
  -moz-transform: translate3d(0, 0, 0);
  -ms-transform: translate3d(0, 0, 0);
  transform: translate3d(0, 0, 0);
  -webkit-backface-visibility: hidden;
  -moz-backface-visibility: hidden;
  -ms-backface-visibility: hidden;
  backface-visibility: hidden;
  -webkit-perspective: 1000;
  -moz-perspective: 1000;
  -ms-perspective: 1000;
  perspective: 1000;
}

index.wxml

<view class="page-swiper" bind:touchstart="handleStart" bind:touchmove="handleMove" bind:touchend="handleEnd">
  <view class="swiper-content" style="width:{{width*list.length}}px">
    <view 
      class="content-slider {{startTime ? 'swiper-transform':''}}" 
      style="left: {{offset}}px" 
      wx:for-items="{{list}}" 
      wx:key="{{item}}" 
      data-index="{{index}}"
    >
    {{item.title}}
  </view>
  </view>
</view>

抽象为工具 swiper.js

function swiper(that) {
  that.handleStart = handleStart
  that.handleMove = handleMove
  that.handleEnd = handleEnd
}
/*
* @触摸起点
* @获取起点时间,起点坐标
*/
function handleStart(e){
  const { timeStamp } = e // 起点时间
  const { clientX, clientY } = e.touches[0] //起点坐标
  this.setData({ 
    startX: clientX,
    startY: clientY,
    startTime: timeStamp
  })
}
/*
* @触摸变换
* @坐标轴
* X -> 右, X轴自左向右自增
* Y -> 下, Y轴自上向下自增
*
* @上下滑动(|Y| > |X|),终止计算
* @左右滑动(|Y| < |X|),终点X坐标 - 起点X坐标 > 0
* > 0;(页面向右滑动,偏移距离增大。偏移距离 = offsetOld + |X|)
* < 0;(页面向左滑动,偏移距离减小。偏移距离 = offsetOld - |X|)
*
*/
function handleMove(e){ // 坐标变换,触摸变换触发页面左右滑动
  const { clientX, clientY } = e.touches[0]
  let { startX, startY, offsetOld } = this.data
  let _X = clientX - startX,
      _Y = clientY - startY
  if(Math.abs(_X) <= Math.abs(_Y)) return
  this.setData({ offset: offsetOld + _X })
}
/*
* @触摸结束
*
* @上下滑动(|Y| > |X|),终止计算
* @左右滑动(|Y| < |X|)
*
* @快速滑动: 时间最长小于300ms,最短距离50触发滑动事件  T < 300 && |X| >= 50
* @慢速滑动: T > 300 && |X| >= width/2
* index = 0 终止右移(X > 0),并复原move效果
* index = last 终止左移(X < 0),并复原move效果
*/
function handleEnd(e){ // 坐标变换终止
  const { timeStamp, target: { dataset: { index } } } = e // index 小圆点变换状态
  const { clientX, clientY } = e.changedTouches[0]
  let { list, startX, startY, startTime, width, offset, offsetOld } = this.data
  let T = timeStamp - startTime,
      _X = clientX - startX,
      _Y = clientY - startY,
      X = Math.abs(_X),
      Y = Math.abs(_Y)
  if(X < Y || T < 300 && X < 50 || T >= 300 && X < Math.round(width/2) || index == 0 && _X > 0 || index == list.length - 1 &&  _X < 0) {
    this.setData({
      offset: offsetOld
    })
  }else {
    if(_X < 0) width = -width
      this.setData({
        offset: offsetOld + width,
        offsetOld: offsetOld + width,
      })
  }
}
module.exports = swiper 

修改index.js

const swiper = require('~/util/swiper')
Page({
  data: {
    list: [
      {
        page: '',
        title: '展览展览'
      },
      {
        page: '',
        title: 'VIP专区VIP专区'
      },
      {
        page: '',
        title: '购票购票购票'
      },
      {
        page: '',
        title: '动态动态动态'
      }
    ],
    offsetOld: 0, // 保留距离状态 
    offset: 0, // 向左移动的距离 
    startX: 0, // X轴起点坐标
    startY: 0, // Y轴起点坐标
    startTime: 0, // 触摸起点时间
    width: 375 //默认屏幕宽度
  },
  /*
  * @获取设备宽度
  */
  onLoad() {
    const res = wx.getSystemInfoSync()
    this.setData({ width: res.windowWidth })
    swiper(this)
  }
})

转载于:https://my.oschina.net/igoryuyu/blog/1935405

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值