js仿QQ中对联系人向左滑动、滑出删除按钮的操作


Posted in Javascript onApril 07, 2016

本文实例为大家分享实现类似QQ中对联系人的操作:向左滑动,滑出删除按钮。滑动超过一半时松开则自动滑到底,不到一半时松开则返回原处。

js仿QQ中对联系人向左滑动、滑出删除按钮的操作

纯js实现

使用了h5的touchmove等事件,以及用js动态改变css3的translate属性来达到动画效果:

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <meta name="viewport" id="viewport" content="width=device-width, initial-scale=1">
 <title>html5向左滑动删除特效</title>
 <style>
 * {
 padding: 0;
 margin: 0;
 list-style: none;
 }
 
 header {
 background: #f7483b;
 border-bottom: 1px solid #ccc
 }
 
 header h2 {
 text-align: center;
 line-height: 54px;
 font-size: 16px;
 color: #fff
 }
 
 .list-ul {
 overflow: hidden
 }
 
 .list-li {
 line-height: 60px;
 border-bottom: 1px solid #fcfcfc;
 position: relative;
 padding: 0 12px;
 color: #666;
 background: #f2f2f2;
 -webkit-transform: translateX(0px);
 }
 
 .btn {
 position: absolute;
 top: 0;
 right: -80px;
 text-align: center;
 background: #ffcb20;
 color: #fff;
 width: 80px
 }
 </style>
 <script>
 /*
 * 描述:html5苹果手机向左滑动删除特效
 */
 window.addEventListener('load', function() {
 var initX; //触摸位置
 var moveX; //滑动时的位置
 var X = 0; //移动距离
 var objX = 0; //目标对象位置
 window.addEventListener('touchstart', function(event) {
  event.preventDefault();
  var obj = event.target.parentNode;
  if (obj.className == "list-li") {
  initX = event.targetTouches[0].pageX;
  objX = (obj.style.WebkitTransform.replace(/translateX\(/g, "").replace(/px\)/g, "")) * 1;
  }
  if (objX == 0) {
  window.addEventListener('touchmove', function(event) {
   event.preventDefault();
   var obj = event.target.parentNode;
   if (obj.className == "list-li") {
   moveX = event.targetTouches[0].pageX;
   X = moveX - initX;
   if (X >= 0) {
    obj.style.WebkitTransform = "translateX(" + 0 + "px)";
   } else if (X < 0) {
    var l = Math.abs(X);
    obj.style.WebkitTransform = "translateX(" + -l + "px)";
    if (l > 80) {
    l = 80;
    obj.style.WebkitTransform = "translateX(" + -l + "px)";
    }
   }
   }
  });
  } else if (objX < 0) {
  window.addEventListener('touchmove', function(event) {
   event.preventDefault();
   var obj = event.target.parentNode;
   if (obj.className == "list-li") {
   moveX = event.targetTouches[0].pageX;
   X = moveX - initX;
   if (X >= 0) {
    var r = -80 + Math.abs(X);
    obj.style.WebkitTransform = "translateX(" + r + "px)";
    if (r > 0) {
    r = 0;
    obj.style.WebkitTransform = "translateX(" + r + "px)";
    }
   } else { //向左滑动
    obj.style.WebkitTransform = "translateX(" + -80 + "px)";
   }
   }
  });
  }

 })
 window.addEventListener('touchend', function(event) {
  event.preventDefault();
  var obj = event.target.parentNode;
  if (obj.className == "list-li") {
  objX = (obj.style.WebkitTransform.replace(/translateX\(/g, "").replace(/px\)/g, "")) * 1;
  if (objX > -40) {
   obj.style.WebkitTransform = "translateX(" + 0 + "px)";
   objX = 0;
  } else {
   obj.style.WebkitTransform = "translateX(" + -80 + "px)";
   objX = -80;
  }
  }
 })
 })
 </script>
</head>

<body>
 <header>
 <h2>消息列表</h2>
 </header>
 <section class="list">
 <ul class="list-ul">
  <li id="li" class="list-li">
  <div class="con">
   你的快递到了,请到楼下签收
  </div>
  <div class="btn">删除</div>
  </li>
  <li class="list-li">
  <div class="con">
   哇,你在干嘛,快点来啊就等你了
  </div>
  <div class="btn">删除</div>
  </li>
 </ul>
 </section>
</body>

</html>

做成zepto插件
实际项目中,我们可能有很多个地方会用到这个功能。现在我们将这个功能做成zepto插件,方便后面使用。

这个插件,我们仅实现这个功能,然后传入参数(删除按钮的样式名),让程序在js中计算所需要滑动的距离,方便复用。

zepto.touchWipe.js

/**
 * zepto插件:向左滑动删除动效
 * 使用方法:$('.itemWipe').touchWipe({itemDelete: '.item-delete'});
 * 参数:itemDelete 删除按钮的样式名
 */
;
(function($) {
 $.fn.touchWipe = function(option) {
 var defaults = {
  itemDelete: '.item-delete', //删除元素
 };
 var opts = $.extend({}, defaults, option); //配置选项

 var delWidth = $(opts.itemDelete).width();

 var initX; //触摸位置
 var moveX; //滑动时的位置
 var X = 0; //移动距离
 var objX = 0; //目标对象位置
 $(this).on('touchstart', function(event) {
  event.preventDefault();
  var obj = this;
  initX = event.targetTouches[0].pageX;
  objX = (obj.style.WebkitTransform.replace(/translateX\(/g, "").replace(/px\)/g, "")) * 1;
  if (objX == 0) {
  $(this).on('touchmove', function(event) {
   event.preventDefault();
   var obj = this;
   moveX = event.targetTouches[0].pageX;
   X = moveX - initX;
   if (X >= 0) {
   obj.style.WebkitTransform = "translateX(" + 0 + "px)";
   } else if (X < 0) {
   var l = Math.abs(X);
   obj.style.WebkitTransform = "translateX(" + -l + "px)";
   if (l > delWidth) {
    l = delWidth;
    obj.style.WebkitTransform = "translateX(" + -l + "px)";
   }
   }
  });
  } else if (objX < 0) {
  $(this).on('touchmove', function(event) {
   event.preventDefault();
   var obj = this;
   moveX = event.targetTouches[0].pageX;
   X = moveX - initX;
   if (X >= 0) {
   var r = -delWidth + Math.abs(X);
   obj.style.WebkitTransform = "translateX(" + r + "px)";
   if (r > 0) {
    r = 0;
    obj.style.WebkitTransform = "translateX(" + r + "px)";
   }
   } else { //向左滑动
   obj.style.WebkitTransform = "translateX(" + -delWidth + "px)";
   }
  });
  }

 })
 $(this).on('touchend', function(event) {
  event.preventDefault();
  var obj = this;
  objX = (obj.style.WebkitTransform.replace(/translateX\(/g, "").replace(/px\)/g, "")) * 1;
  if (objX > -delWidth / 2) {
  obj.style.transition = "all 0.2s";
  obj.style.WebkitTransform = "translateX(" + 0 + "px)";
  obj.style.transition = "all 0";
  objX = 0;
  } else {
  obj.style.transition = "all 0.2s";
  obj.style.WebkitTransform = "translateX(" + -delWidth + "px)";
  obj.style.transition = "all 0";
  objX = -delWidth;
  }
 })

 //链式返回
 return this;
 };

})(Zepto);

touchWipe.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" id="viewport" content="width=device-width, initial-scale=1">
<title>html5向左滑动删除特效</title>

<style>
 *{ padding:0; margin:0; list-style: none;}
 header{ background: #f7483b; border-bottom: 1px solid #ccc}
 header h2{ text-align: center; line-height: 54px; font-size: 16px; color: #fff}
 .list-ul{ overflow: hidden}
 .list-li{ line-height: 60px; border-bottom: 1px solid #fcfcfc; position:relative;padding: 0 12px; color: #666;
  background: #f2f2f2;
  -webkit-transform: translateX(0px);
 }
 .btn{ position: absolute; top: 0; right: -80px; text-align: center; background: #ffcb20; color: #fff; width: 80px}
</style>

</head>
<body>
<header>
 <h2>消息列表</h2>
</header>
<section class="list">
 <ul class="list-ul">
  <li id="li" class="list-li">
   <div class="con">
    你的快递到了,请到楼下签收
   </div>
   <div class="btn">删除</div>
  </li>
  <li class="list-li">
   <div class="con">
    哇,你在干嘛,快点来啊就等你了
   </div>
   <div class="btn">删除</div>
  </li>
 </ul>
</section>

<p>X: <span id="X"></span></p>
<p>objX: <span id="objX"></span></p>
<p>initX: <span id="initX"></span></p>
<p>moveX: <span id="moveX"></span></p>

<script type="text/javascript" src="http://apps.bdimg.com/libs/zepto/1.1.4/zepto.min.js"></script>
<script type="text/javascript" src="zepto.touchWipe.js"></script>
<script type="text/javascript">
 $(function() {
 $('.list-li').touchWipe({itemDelete: '.btn'});
 });

</script>
</body>
</html>

效果:

js仿QQ中对联系人向左滑动、滑出删除按钮的操作

实际项目中的应用效果:

js仿QQ中对联系人向左滑动、滑出删除按钮的操作

消除BUG
到上面一步,基本实现了我们所需要的功能。但是有几个问题

1. 右边的删除按钮点击失灵,因为span无法冒泡到大按钮上;

2. 非常严重的问题,我们给div添加了touchmove事件同时用preventDefault()屏蔽了原始的浏览器事件,导致上下滑动div的时候 页面无法滚动了!

 第一个问题比较容易解决,我们把span直接去掉,将“删除”写到css中的:before里,像这样:

.itemWipe .item-delete:before {
 content: '删除';
 color: #fff;
}

对于第二个问题,网上说用iscroll来解决。我们这里参考手机QQ中对联系人的滑动操作。

大致原理:在滑动最开始的时候,判断是Y轴的移动多 还是 X轴的移动多。 如果是X轴移动大,则判断为滑动删除操作,我们再使用preventDefault();

更多关于滑动效果的专题,请点击下方链接查看:

以上就是本文的全部内容,希望对大家的学习有所帮助。

Javascript 相关文章推荐
摘自启点的main.js
Apr 20 Javascript
JavaScript 一道字符串分解的题目
Aug 03 Javascript
Javascript 检测键盘按键信息及键码值对应介绍
Jan 03 Javascript
Javascript获取当前日期的农历日期代码
Oct 08 Javascript
AngularJS自定义服务与fliter的混合使用
Nov 24 Javascript
Vue.js实现简单ToDoList 前期准备(一)
Dec 01 Javascript
jQuery中hover方法搭配css的hover选择器,实现选中元素突出显示方法
May 08 jQuery
VUE2.0+Element-UI+Echarts封装的组件实例
Mar 02 Javascript
Angular4学习笔记router的简单使用
Mar 30 Javascript
JavaScript实现表单注册、表单验证、运算符功能
Oct 15 Javascript
JavaScript代码模拟鼠标自动点击事件示例
Aug 07 Javascript
解决vue项目中某一页面不想引用公共组件app.vue的问题
Aug 14 Javascript
jQuery实现简单滚动动画效果
Apr 07 #Javascript
基于javascript bootstrap实现生日日期联动选择
Apr 07 #Javascript
原生js制作日历控件实例分享
Apr 06 #Javascript
基于HTML模板和JSON数据的JavaScript交互(移动端)
Apr 06 #Javascript
JavaScript中实现无缝滚动、分享到侧边栏实例代码
Apr 06 #Javascript
jQuery实现内容定时切换效果完整实例
Apr 06 #Javascript
jQuery隐藏和显示效果实现
Apr 06 #Javascript
You might like
php 文件上传后缀名与文件类型对照表(几乎涵盖所有文件)
2010/05/16 PHP
php与java通过socket通信的实现代码
2013/10/21 PHP
php和jquery实现地图区域数据统计展示数据示例
2014/02/12 PHP
php实现比较全的数据库操作类
2015/06/18 PHP
PHP中使用mpdf 导出PDF文件的实现方法
2018/10/22 PHP
PHP中str_split()函数的用法讲解
2019/04/11 PHP
ext实现完整的登录代码
2008/08/08 Javascript
[Web]防止用户复制页面内容和另存页面的方法
2009/02/06 Javascript
actionscript与javascript的区别
2011/05/25 Javascript
浅谈javascript六种数据类型以及特殊注意点
2013/12/20 Javascript
浏览器窗口加载和大小改变事件示例
2014/02/27 Javascript
JQuery获取与设置HTML元素的内容或文本的实现代码
2014/06/20 Javascript
JS实现仿新浪黄色经典滑动门效果代码
2015/09/27 Javascript
javascript日期验证之输入日期大于等于当前日期
2015/12/13 Javascript
jquery获取点击控件的绝对位置简单实例
2016/10/13 Javascript
JavaScript 实现的checkbox经典实例分享
2016/10/16 Javascript
Webpack+Vue如何导入Jquery和Jquery的第三方插件
2017/02/20 Javascript
jQuery EasyUI 为Combo,Combobox添加清除值功能的实例
2017/04/13 jQuery
Auto.js自动收取自己和好友蚂蚁森林能量脚本
2018/06/28 Javascript
node.js如何操作MySQL数据库
2020/10/29 Javascript
使用webpack5从0到1搭建一个react项目的实现步骤
2020/12/16 Javascript
[02:27]刀塔重生降临
2015/10/14 DOTA
Python 编码规范(Google Python Style Guide)
2018/05/05 Python
解决在Python编辑器pycharm中程序run正常debug错误的问题
2019/01/17 Python
Python序列化与反序列化pickle用法实例
2019/11/11 Python
python 用 xlwings 库 生成图表的操作方法
2019/12/22 Python
猫途鹰英国网站:TripAdvisor英国(旅游社区和旅游评论)
2016/08/30 全球购物
Nike墨西哥官网:Nike MX
2020/08/30 全球购物
七年级地理教学反思
2014/01/26 职场文书
《雨点》教学反思
2014/02/12 职场文书
大学生推广普通话演讲稿
2014/09/21 职场文书
2014年信访工作总结
2014/11/17 职场文书
驳回起诉民事裁定书
2015/05/19 职场文书
幸福来敲门观后感
2015/06/04 职场文书
学会Python数据可视化必须尝试这7个库
2021/06/16 Python
利用Java连接Hadoop进行编程
2022/06/28 Java/Android