Wechat applet left slide delete operation (similar to wechat, QQ)

This function was done in the project of the last small program, but it was not recorded at that time. Today, I specially made a small demo and put it on github. Next time I meet it in the development, I can directly take it down for code reuse. The effect is very simple, similar to the effect of deleting chat bar with wechat buckle. If you want to slide left, the delete button will appear. Click it to delete.

github address: https://github.com/wangxiaoting666/swipeleft-delete

wxml:

<!--index.wxml-->
<view class="container">
  <scroll-view style='height:{{height}}px;' scroll-y='{{scrollY}}' class='msg-list' bindscroll='onScroll'>
    <view wx:for="{{msgList}}" wx:key="id" class='msg-item' animation='{{item.wrapAnimation}}'>
      <view id='{{item.id}}' class='msg' animation='{{item.animation}}' bindtouchstart='ontouchstart' bindtouchmove='ontouchmove' bindtouchend='ontouchend'>
        <image class='header-img' src="{{item.headerImg}}"></image>
        <text class='user-name'>{{item.carid}}</text>
        <text class='msg-text'>{{item.msgText}}</text>
        <image class='site-img' src="{{item.siteImg}}"></image>
      </view>
      <view class='msg-menu'>
        <view id='{{item.id}}' class='menu-delete' bindtap='onDeleteMsgTap' bindlongtap='onDeleteMsgLongtap'>
          delete
        </view>
        <view id='{{item.id}}' class='menu-mark' bindtap='onMarkMsgTap' bindlongtap='onMarkMsgLongtap'>
          Test drive
        </view>
      </view>
    </view>
  </scroll-view>
</view>

wxss:

/**index.wxss**/

::-webkit-scrollbar {
  width: 0;
  height: 0;
  color: transparent;
}

.msg-item {
  width: 100%;
  height: 150rpx;
  border-bottom: 1rpx solid rgb(233, 233, 233);
  position: relative;
  left: 0;
  top: 0;
  overflow: hidden;
}

.msg {
  position: absolute;
  width: 100%;
  height: 150rpx;
  left: 0;
  top: 0;
  z-index: 100;
  background-color: #fff;
}

.header-img {
  position: absolute;
  width: 100rpx;
  height: 100rpx;
  left: 30rpx;
  top: 40rpx;
  border-radius: 10%;
}

.site-img {
  position: absolute;
  width: 70rpx;
  height: 70rpx;
  right: 30rpx;
  top: 40rpx;
  border-radius: 10%;
}

.user-name {
  position: absolute;
  left: 150rpx;
  top: 33rpx;
  font-weight: 600;
  font-size: 35rpx;
}

.msg-text {
  position: absolute;
  left: 150rpx;
  bottom: 30rpx;
  font-size: 80%;
  color: rgb(127, 127, 127);
}

.msg-menu {
  position: absolute;
  width: 100%;
  height: 150rpx;
  left: 0;
  top: 0;
  z-index: 0;
}

.menu-delete {
  position: absolute;
  width: 150rpx;
  height: 148rpx;
  top: 1rpx;
  right: 0;
  background-color: rgb(255, 58, 50);
  color: #fff;
  text-align: center;
  line-height: 150rpx;
}

.menu-mark {
  position: absolute;
  width: 200rpx;
  height: 148rpx;
  top: 1rpx;
  right: 150rpx;
  background-color: rgb(200, 199, 205);
  color: #fff;
  text-align: center;
  line-height: 150rpx;
}

/* Bottom button */

.Scancode {
  font-size: 39rpx;
  background: rgb(82, 80, 80);
  position: fixed;
  bottom: 0;
  display: flex;
  width: 100%;
  justify-content: center;
  color: #fff;
  border-radius: 0px;
}

.search {
  width: 80rpx;
  height: 80rpx;
  line-height: 80rpx;
  background: #fff;
  border: 1px solid #c8c8c8;
  position: fixed;
  bottom: 130rpx;
  left: 16rpx;
  display: flex;
  justify-content: center;
  border-radius: 50rpx;
  /* -webkit-box-shadow:3px 3px 3px #c8c8c8 ;
-moz-box-shadow:3px 3px 3px #c8c8c8 ;
box-shadow:3px 3px 3px #c8c8c8 ; */
}

.search .img {
  width: 40rpx;
  height: 40rpx;
  margin-top: 10rpx;
}

.user {
  width: 80rpx;
  height: 80rpx;
  line-height: 80rpx;
  border: 1px solid #c8c8c8;
  background: #fff;
  position: fixed;
  bottom: 130rpx;
  right: 16rpx;
  display: flex;
  color: #fff;
  justify-content: center;
  border-radius: 50rpx;
  /* -webkit-box-shadow:3px 3px 3px #c8c8c8 ;
-moz-box-shadow:3px 3px 3px #c8c8c8 ;
box-shadow:3px 3px 3px #c8c8c8 ; */
}

.user .img {
  width: 40rpx;
  height: 40rpx;
  margin-top: 10rpx;
}

js

//index.js
//Get application instance

var app = getApp()

Page({
  data: {
    msgList:[],
    height:0,
    scrollY:true
  },
  swipeCheckX:35, //Threshold to activate detection slip
  swipeCheckState:0, //0 not activated 1 activated
  maxMoveLeft:185, //Maximum left slip distance of message list item
  correctMoveLeft:175, //Left slide distance when menu is displayed
  thresholdMoveLeft: 75,//Left slide threshold, if it is exceeded, the menu will be displayed
  lastShowMsgId:'', //Record the message id of the last menu displayed
  moveX:0,  //Record translation distance
  showState:0, //0 menu not displayed 1 menu displayed
  touchStartState:0, // Status 0 at the beginning of touch menu 1 display menu
  swipeDirection:0, //Trigger horizontal sliding 0: not triggered 1: trigger horizontal sliding 2: trigger vertical sliding
  onLoad: function() {
    this.pixelRatio = app.data.deviceInfo.pixelRatio;
    var windowHeight = app.data.deviceInfo.windowHeight;  
    var height = windowHeight;
    for (var i = 0; i < 5; i++) {
      var msg = {};
      msg.carid = '' + 'Shanghai D086' + i+1;
      msg.msgText = '10801:10001'
      msg.id = 'id-' + i+1;
      msg.headerImg = '../../img/car.png';
      msg.siteImg = '../../img/site.png';
      this.data.msgList.push(msg);
    }
    this.setData({msgList:this.data.msgList, height:height});
  },

  ontouchstart: function(e) {
    if (this.showState === 1) {
      this.touchStartState = 1;
      this.showState = 0;
      this.moveX = 0;
      this.translateXMsgItem(this.lastShowMsgId, 0, 200);
      this.lastShowMsgId = "";
      return;
    }
    this.firstTouchX = e.touches[0].clientX;
    this.firstTouchY = e.touches[0].clientY;
    if (this.firstTouchX > this.swipeCheckX) {
      this.swipeCheckState = 1;
    }
    this.lastMoveTime = e.timeStamp;
  },

  ontouchmove: function(e) {
    if (this.swipeCheckState === 0) {
      return;
    }
    //When there is menu display at the beginning of touch, the sliding operation is not handled
    if (this.touchStartState === 1) {
      return;
    }
    var moveX = e.touches[0].clientX - this.firstTouchX;
    var moveY = e.touches[0].clientY - this.firstTouchY;
    //Vertical sliding has been triggered, sliding operation is handled by scroll view
    if (this.swipeDirection === 2) {
      return;
    }
    //Sliding direction not triggered
    if (this.swipeDirection === 0) {
      console.log(Math.abs(moveY));
      //Trigger vertical operation
      if (Math.abs(moveY) > 4) {
        this.swipeDirection = 2;

        return;
      }
      //Trigger horizontal operation
      if (Math.abs(moveX) > 4) {
        this.swipeDirection = 1;
        this.setData({scrollY:false});
      }
      else {
        return;
      }
        
    }
    //Disable vertical scrolling
    // if (this.data.scrollY) {
    //   this.setData({scrollY:false});
    // }

    this.lastMoveTime = e.timeStamp;
    //Dealing with boundary conditions
    if (moveX > 0) {
      moveX = 0;
    }
    //Detect the maximum left slip distance
    if (moveX < -this.maxMoveLeft) {
      moveX = -this.maxMoveLeft;
    }
    this.moveX = moveX;
    this.translateXMsgItem(e.currentTarget.id, moveX, 0);
  },
  ontouchend: function(e) {
    this.swipeCheckState = 0;
    var swipeDirection = this.swipeDirection;
    this.swipeDirection = 0;
    if (this.touchStartState === 1) {
      this.touchStartState = 0;
      this.setData({scrollY:true});
      return;
    } 
    //Scroll vertically, ignore
    if (swipeDirection !== 1) {
      return;
    }
    if (this.moveX === 0) {
      this.showState = 0;
      //Activate vertical scrolling when the menu is not displayed
      this.setData({scrollY:true});
      return;
    }
    if (this.moveX === this.correctMoveLeft) {
      this.showState = 1;
      this.lastShowMsgId = e.currentTarget.id;
      return;
    }  
    if (this.moveX < -this.thresholdMoveLeft) {
      this.moveX = -this.correctMoveLeft;
      this.showState = 1;
      this.lastShowMsgId = e.currentTarget.id;
    }
    else {
      this.moveX = 0;
      this.showState = 0;
      //Do not display menu, activate vertical scrolling
      this.setData({scrollY:true});
    }
    this.translateXMsgItem(e.currentTarget.id, this.moveX, 500);
    //this.translateXMsgItem(e.currentTarget.id, 0, 0);
  },
  onDeleteMsgTap: function(e) {
    this.deleteMsgItem(e);
  },
  onDeleteMsgLongtap: function(e) {
    console.log(e);
  },
  onMarkMsgTap: function(e) {
    console.log(e);
  },
  onMarkMsgLongtap: function(e) {
    console.log(e);
  },
  getItemIndex: function(id) {
    var msgList = this.data.msgList;
    for (var i = 0; i < msgList.length; i++) {
      if (msgList[i].id === id) {
        return i;
      }
    }
    return -1;
  },
  deleteMsgItem: function(e) {
    var animation = wx.createAnimation({duration:200});
    animation.height(0).opacity(0).step();
    this.animationMsgWrapItem(e.currentTarget.id, animation);
    var s = this;
    setTimeout(function() {
      var index = s.getItemIndex(e.currentTarget.id);
      s.data.msgList.splice(index, 1);
      s.setData({msgList: s.data.msgList});
    }, 200);
    this.showState = 0;
    this.setData({scrollY:true});
  },
  translateXMsgItem: function(id, x, duration) {
    var animation = wx.createAnimation({duration:duration});
    animation.translateX(x).step();
    this.animationMsgItem(id, animation);
  },
  animationMsgItem: function(id, animation) {
    var index = this.getItemIndex(id);
    var param = {};
    var indexString = 'msgList[' + index + '].animation';
    param[indexString] = animation.export();
    this.setData(param);
  },
  animationMsgWrapItem: function(id, animation) {
    var index = this.getItemIndex(id);
    var param = {};
    var indexString = 'msgList[' + index + '].wrapAnimation';
    param[indexString] = animation.export();
    this.setData(param);
  },


})

Original author: miss qiche. Technology blog: https://www.jianshu.com/u/05f416aefbe1
Post-90s front-end sister, love programming, love operation, love tossing. For a long time, we must summarize the technical problems encountered in our work.

Popular recommendation: front end, Java, product manager, wechat applet, Python and other 200G resource collection and large-scale release

Keywords: github Programming Java Python

Added by ptraffick on Tue, 03 Dec 2019 14:07:33 +0200