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 相关文章推荐
自动生成文章摘要的代码[JavaScript 版本]
Mar 20 Javascript
用JS实现一个页面多个css样式实现
May 29 Javascript
javascript和HTML5利用canvas构建猜牌游戏实现算法
Jul 17 Javascript
js编码、解码函数介绍及其使用示例
Sep 05 Javascript
jQuery插件简单实现方法
Jul 18 Javascript
JavaScript设计模式经典之命令模式
Feb 24 Javascript
JS实现兼容火狐及IE iframe onload属性的遮罩层隐藏及显示效果
Aug 23 Javascript
Angular 2父子组件数据传递之@Input和@Output详解(下)
Jul 05 Javascript
深入浅析javascript继承体系
Oct 23 Javascript
基于express中路由规则及获取请求参数的方法
Mar 12 Javascript
JavaScript变量作用域及内存问题实例分析
Jun 10 Javascript
js判断两个数组相等的5种方法
May 06 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
PHPMyadmin 配置文件详解(配置)
2009/12/03 PHP
PHP文件打开、关闭、写入的判断与执行代码
2011/05/24 PHP
PHP字符编码问题之GB2312 VS UTF-8解决方法
2011/06/23 PHP
PHP session文件独占锁引起阻塞问题解决方法
2015/05/12 PHP
浅析PHP类的反射来实现依赖注入过程
2018/02/06 PHP
PHP mongodb操作类定义与用法示例【适合mongodb2.x和mongodb3.x】
2018/06/16 PHP
laravel 实现向公共模板中传值 (view composer)
2019/10/22 PHP
用jquery与css打造个性化的单选框和复选框
2010/10/20 Javascript
js复制到剪切板的实例方法
2013/06/28 Javascript
Javascript中的匿名函数与封装介绍
2015/03/15 Javascript
javascript实现的登陆遮罩效果汇总
2015/11/09 Javascript
JavaScript转换与解析JSON方法实例详解
2015/11/24 Javascript
jQuery选择器及jquery案例详解(必看)
2016/05/20 Javascript
Angular.js中用ng-repeat-start实现自定义显示
2016/10/18 Javascript
基于bootstrap实现bootstrap中文网巨幕效果
2017/05/02 Javascript
JavaScript中的连续赋值问题实例分析
2019/07/12 Javascript
JS co 函数库的含义和用法实例总结
2020/04/08 Javascript
[00:48]完美“圣”典2016风云人物:xiao8宣传片
2016/11/30 DOTA
Python 元组(Tuple)操作详解
2014/03/11 Python
Python中用format函数格式化字符串的用法
2015/04/08 Python
python 添加用户设置密码并发邮件给root用户
2016/07/25 Python
用python结合jieba和wordcloud实现词云效果
2017/09/05 Python
Python实现的选择排序算法示例
2017/11/29 Python
linux环境中没有网络怎么下载python
2019/07/07 Python
Django文件存储 自己定制存储系统解析
2019/08/02 Python
python对象销毁实例(垃圾回收)
2020/01/16 Python
VS2019+python3.7+opencv4.1+tensorflow1.13配置详解
2020/04/16 Python
解决python运行启动报错问题
2020/06/01 Python
美国高端婴童品牌:Hanna Andersson
2016/10/30 全球购物
Baracuta官方网站:Harrington夹克,G9,G4,G10等
2018/03/06 全球购物
假日旅行社实习自我鉴定
2013/09/24 职场文书
路政管理专业个人自荐信范文
2013/11/30 职场文书
常务副总经理岗位职责
2014/04/12 职场文书
优秀大学生事迹材料
2014/12/24 职场文书
2015年国庆节慰问信
2015/03/23 职场文书
jQuery实现影院选座订座效果
2021/04/13 jQuery