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 相关文章推荐
CSS+Jquery实现页面圆角框方法大全
Dec 24 Javascript
js或css实现滚动广告的几种方案
Jan 28 Javascript
jQuery弹出(alert)select选择的值
Apr 21 Javascript
JS实现超过长度限制后自动跳转下一款文本框的方法
Feb 23 Javascript
使用jQuery操作HTML的table表格的实例解析
Mar 13 Javascript
Bootstrap实现水平排列的表单
Jul 04 Javascript
完美实现八种js焦点轮播图(上篇)
Jul 18 Javascript
JS实现加载时锁定HTML页面元素的方法
Jun 24 Javascript
老生常谈javascript的面向对象思想
Aug 22 Javascript
JS前端知识点offset,scroll,client,冒泡,事件对象的应用整理总结
Jun 27 Javascript
详解Vue之计算属性
Jun 20 Javascript
用js实现放大镜效果
Oct 28 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简单对象与数组的转换函数代码(php多层数组和对象的转换)
2011/05/18 PHP
php删除页面记录 同时刷新页面 删除条件用GET方式获得
2012/01/10 PHP
php中选择什么接口(mysql、mysqli)访问mysql
2013/02/06 PHP
php 判断服务器操作系统的类型
2014/02/17 PHP
Laravel执行migrate命令提示:No such file or directory的解决方法
2016/03/16 PHP
简单谈谈PHP中的Reload操作
2016/12/12 PHP
PHP实现更改hosts文件的方法示例
2017/08/08 PHP
phpinfo的知识点总结
2019/10/10 PHP
JS获取客户端IP地址、MAC和主机名的7个方法汇总
2014/07/21 Javascript
Egret引擎开发指南之运行项目
2014/09/03 Javascript
jQuery实现向下滑出的二级菜单效果实例
2015/08/22 Javascript
JavaScript函数的调用以及参数传递
2015/10/21 Javascript
js中获取键盘按下键值event.keyCode、event.charCode和event.which的兼容性详解
2017/03/15 Javascript
详解vue axios中文文档
2017/09/12 Javascript
Node解决简单重复问题系列之Excel内容的获取
2018/01/02 Javascript
vue单个组件实现无限层级多选菜单功能
2018/04/10 Javascript
JS关于刷新页面的相关总结
2018/05/09 Javascript
JavaScript如何处理移动端拍摄图片旋转问题
2019/11/16 Javascript
详解JavaScript 中的批处理和缓存
2020/11/19 Javascript
[03:07]DOTA2英雄基础教程 冰霜诅咒极寒幽魂
2013/12/06 DOTA
在Django的模型和公用函数中使用惰性翻译对象
2015/07/27 Python
python使用sessions模拟登录淘宝的方式
2019/08/16 Python
numpy.linalg.eig() 计算矩阵特征向量方式
2019/11/29 Python
CSS3的一个简单导航栏实现
2015/08/03 HTML / CSS
使用css实现android系统的loading加载动画
2019/07/25 HTML / CSS
纯HTML5+CSS3制作生日蛋糕代码
2016/11/16 HTML / CSS
AmazeUI中模态框的实现
2020/08/19 HTML / CSS
Farah官方网站:男士服装及配件
2019/11/01 全球购物
MediaMarkt比利时:欧洲最大电器连锁店
2020/12/21 全球购物
英国珠宝网站Argento: PANDORA、Olivia Burton和Nomination等
2020/05/08 全球购物
一年级班主任寄语
2014/01/19 职场文书
大学生素质拓展活动方案
2014/02/11 职场文书
财务会计大学生自我评价
2014/04/09 职场文书
2015年清明节网上祭英烈留言寄语
2015/03/04 职场文书
联欢会开场白
2015/06/01 职场文书