该组件,主要功能类似于QQ消息列表左滑出现删除、标为已读等按钮的功能;现在的版本用的是纯javaScript编写;后续会跟进 angularJs 开发的类似组件以及jquery的;

下面,就让我们来认识下怎么使用该程序;

  在该程序里,总共分为四个文件:

  1 .css文件夹

  2. img 图片文件夹

  3. js文件

  4. index.html  主页面;

  稍后,你可以自行下载,打开运行观看效果;

  

二、代码讲解

1.此html结构,为不可修改结构

<ul class="list-ul">

  <!--an-slide-li 此样式必须添加在li标签上,为js程序判断是否选中的是要操作的dom元素所用-->
  <li class="list-li an-slide-li">     <!--z-index-up(z-index:层级最高,且覆盖整个li):对应的dom元素,是为了在触发touchStart事件事,可以选中整个li-->
    <div class="z-index-up" onClick="change('新浪博客')"></div>
    <div>
      <div class="list-img">
        <div>
          <img src="img/Tulips.jpg" />
        </div>
      </div>
      <div class="list-contant">
        <div class="list-contant-title"><label>微博已开通</label></div>
        <div class="list-contant-text"><label>第一个,我要发博客</label></div>
      </div>
      <div class="list-time-message">
        <div class="list-time"><span>10:18</span></div>
        <div class="list-message"></div>
      </div>
    </div>
    <div class="btn" onClick="del('1')">
      <div>
        删除
      </div>
    </div>
  </li> </ul>

2. js代码讲解;

  注:该程序主要使用js的三个事件touchstart(手指触摸事件)、startmove(手指移动)、startend(手指离开屏幕)

    请认真阅读以下代码,你会对这三个事件有一个新的认识;让我们一起嗨起来吧!

//在全局运行此程序

window.addEventListener("load", autoLoad, false);
function autoLoad() {
var initX; //触摸位置
var initY;
var moveX; //滑动时的位置
var moveY;
var X = 0; //移动距离
var Y = 0; //y轴移动距离
var objX, sildeWidth = 0; //目标对象位置、功能按钮width(如删除)
//yesClick:是否可以点击列表进行下一步操作; xSilde,ySilde 默认xSilde都为true(做上下 , 左右滑动控制)
var yesClick, xSilde = true,
ySilde = true,
xThink = '1';
window.sessionStorage.setItem("xThink", xThink); //初始化xThink
//开始执行程序
window.addEventListener('touchstart', touchStart, false);
/*手指触屏时的方法*/
function touchStart(event) {
//通过设置的 an-z-index-up 对应dom(目的:可以选中整个li元素) ,获取父元素li ()
var obj = event.target.parentNode;
//获取所有的li元素
var mainLi = document.querySelectorAll(".an-slide-li");
/*当点击的是功能按钮的话,初始化xThink、anObjX*/
if (event.target.className.indexOf("an-function-button") != -1) {
window.sessionStorage.setItem("xThink", '1'); //初始化xThink
window.sessionStorage.setItem("anObjX", '0');
}
/*
*btnStyle: 获取功能按钮,判断一共添加了几个按钮
*btnStyleLength: btnStyle 长度
*setWidth :btnStyle 按钮宽度
*/
var btnStyle, btnStyleLength, setWidth;
sildeWidth = 5;
//设置默认状态下点击列表可进行下一步
yesClick = true;
/*判断如果最终的值小于0 , 关闭已经出现的动画;禁止li点击事件(此值在end方法中会被重新赋值,再作判断)*/
var anObjX = window.sessionStorage.getItem("anObjX");
if (anObjX == null) {
anObjX = 0;
}
if (anObjX < 0) {
event.preventDefault();
for (var i = 0; i < mainLi.length; i++) {
mainLi[i].style.transition = "transform 0.1s"; //延缓动画效果
mainLi[i].style.transform = "translateX(0rem)";
mainLi[i].style.WebkitTition = "transform 0.1s"; //延缓动画效果
mainLi[i].style.WebkitTransform = "translateX(0rem)";
}
yesClick = false;
event.stopPropagation(); //事件冒泡,禁止上下滑动;
}
/*判断是否点中删除按钮*/
if (event.target.parentNode.className === "btn") {
event.target.parentNode.onclick();
}
/*判断手指所在的区域为指定li*/ if (obj.className.indexOf("an-slide-li") != -1) {
initX = event.targetTouches[0].pageX; //获取手指触摸x值
initY = event.targetTouches[0].pageY; //获取手指触摸y值
objX = (obj.style.WebkitTransform.replace(/translateX\(/g, "").replace(/rem\)/g, "")) * 1; //获取WebkitTransform 值;
//自动添加 动画样式
if (!objX) {
for (var i = 0; i < mainLi.length; i++) {
mainLi[i].style.transition = "transform 0.1s"; //延缓动画效果
mainLi[i].style.transform = "translateX(0rem)";
mainLi[i].style.WebkitTition = "transform 0.1s"; //延缓动画效果
mainLi[i].style.WebkitTransform = "translateX(0rem)";
objX = (obj.style.WebkitTransform.replace(/translateX\(/g, "").replace(/rem\)/g, "")) * 1; //获取WebkitTransform 值;
}
}
} /*当=0时,执行touchMove命令*/
//console.log();
if (objX == 0) {
obj.addEventListener('touchmove', touchMove, false);
}
obj.addEventListener('touchend', touchEnd, false);
}
//手指滑动方法
function touchMove(event) {
//event.preventDefault();
/*xThink : 控制当出现动画时(X的最大值),点击其他任何地方动画消失,
*或继续向左滑动,xThink='0',禁止touchMove事件,
*触发end事件,则恢复原状xThink='1'
*/
xThink = window.sessionStorage.getItem("xThink");
var obj = event.target.parentNode;
yesClick = false; //滑动时,点击li效果失效
//判断是否选中的是li
if (obj.className.indexOf("an-slide-li") != -1) { //&&xThink == '1'
moveX = event.targetTouches[0].pageX; //获取移动后的最终X值
moveY = event.targetTouches[0].pageY; //获取移动后的最终Y值
X = (moveX - initX) / 100; //变化中的X值;
Y = (moveY - initY) / 100; //变化中的Y值;
//判断x轴是否可以滑动
if (xSilde) {
//如果X轴的变化值大于等于0,WebkitTransform = 0;不进行动画效果,否则,执行
if (X >= 0 || xThink == '0') {
obj.style.WebkitTransform = "translateX(" + 0 + "rem)";
} else if (X < 0) {
event.preventDefault(); //禁止默认滚动事件
var l = Math.abs(X); //取绝对值X
obj.style.WebkitTransform = "translateX(" + -l + "rem)"; //实现滑动效果,删除按钮出现
//判断是否已经超出设置值
if (l > sildeWidth) {
l = sildeWidth;
obj.style.WebkitTransform = "translateX(" + -l + "rem)";
}
}
//判断X值如果大于15 , 区分左右滑动还是上下滑动
if (Math.abs(X) >= 0.15) {
Y = 0; //禁止上下滑动
ySilde = false; //禁止上下滑动
//yThink = false;//禁止上下滑动
event.preventDefault(); //禁止上下滑动
}
}
/*如果出现向左滑动动画,则在手指离开屏幕之前,不可以上下滚动*/
if (ySilde) { //判断y轴是否可以滑动
if (Math.abs(Y) >= 0.15) {
X = 0; //禁止 左右 滑动
obj.style.WebkitTransform = "translateX(" + 0 + "rem)";
xSilde = false; //禁止 左右 滑动
//event.preventDefault();
}
}
}
}
/*手指离开屏幕方法*/
function touchEnd(event) {
event.preventDefault();
var obj = event.target.parentNode;
xSilde = true;
ySilde = true;
if (obj.className.indexOf("an-slide-li") != -1) {
objX = (obj.style.WebkitTransform.replace(/translateX\(/g, "").replace(/rem\)/g, "")) * 1;
//放开手时,判断objX最终值,如果大于按钮中间值,则使按钮恢复隐藏状态;反之;
if (objX > -(sildeWidth / 4)) {
obj.style.WebkitTransform = "translateX(" + 0 + "rem)";
objX = 0;
xThink = '1';
window.sessionStorage.setItem("xThink", xThink);
window.sessionStorage.setItem("anObjX", objX);
//yesClick = true;
} else {
obj.style.WebkitTransform = "translateX(" + -sildeWidth + "rem)";
objX = -sildeWidth;
window.sessionStorage.setItem("anObjX", objX);
yesClick = false; //禁止点击li事件
xThink = '0';
window.sessionStorage.setItem("xThink", xThink);
}
}
sildeWidth = 0;
//点击li后需要执行的方法
if (event.target.className === "an-z-index-up" && yesClick) {
// scope.goClick();
window.sessionStorage.setItem("anObjX", '0');
}
}
}

3.style  /  css

* {
padding:0;
margin:0;
list-style:none;
}
body {
background:#FFFFF0;
}
header {
width:100%;
background:#00CED1;
border-bottom:1px solid #ccc;
position:fixed;
top:0;
left:0;
z-index:1;
}
header h2 {
text-align:center;
line-height:4rem;
font-size:16px;
color:#fff
}
.list {
padding-top:4.1rem;
}
.list-ul {
top:5px;
overflow:hidden;
}
.list-li {
height:3.8rem;
/*width:100%;
*/
line-height:3.8rem;
border-bottom:1px solid #dcd6d6;
position:relative;
padding:0 8px;
color:#666;
background:#FFFFF0;
-webkit-transform:translateX(0px);
transition:transform 0.2s;
-webkit-transition:transform 0.2s;
/*3d加速*/
webkit-transform:translate3d(0,0,0);
-moz-transform:translate3d(0,0,0);
-ms-transform:translate3d(0,0,0);
-o-transform:translate3d(0,0,0);
transform:translate3d(0,0,0);
}
.z-index-up {
z-index:9999;
width:100%;
height:3.8rem;
padding:0;
position:absolute;
/* background:red;
*/
}
/* 头像 */
.list-li .list-img {
float:left;
width:15%;
padding-top:.49rem;
}
.list-li .list-img div {
width:2.8rem;
height:2.8rem;
padding-left:.2rem;
/*background:url("../img/Tulips.jpg") no-repeat center;
*/
/*border:0;
*/
/*border-radius:50%;
*/
}
.list-li .list-img div img {
width:2.8rem;
height:2.8rem;
border-radius:50%;
}
/* 文字内容 */
.list-li .list-contant {
float:left;
width:65%;
padding-top:0.25rem;
padding-left:.4rem;
}
.list-li .list-contant .list-contant-title {
height:1.7rem;
line-height:2rem;
}
.list-li .list-contant .list-contant-title label {
font-size:14px;
font-weight:bold;
}
.list-li .list-contant .list-contant-text {
height:1.7rem;
line-height:1.3rem;
}
.list-li .list-contant .list-contant-text label {
font-size:12px;
}
/* 时间 消息提醒 */
.list-time-message {
float:left;
width:16%;
padding-top:0.25rem;
padding-left:.46rem;
}
.list-time-message .list-time {
float:left;
height:1.7rem;
width:100%;
line-height:1.7rem;
font-size:10px;
text-align:right;
}
.list-time-message .list-time span {
padding-right:.8rem;
}
.list-time-message .list-message {
float:left;
/* height:1.7rem;
line-height:1.7rem;
*/
}
/* 按钮 */
.btn {
position:absolute;
top:0;
right:-80px;
text-align:center;
background:#FF0000;
border-bottom:1px solid #FF0000;
color:#fff;
width:80px;
height:3.8rem;
line-height:3.8rem;
}
.btn div {
/*padding-right:.6rem;
*/
}
/* 提示框 */
.contant-prompt {
width:100%;
text-align:center;
z-index:1;
opacity:0.9;
display:none;
}
.contant-prompt .prompt {
position:absolute;
bottom:0;
left:0;
right:0;
height:2rem;
text-align:center;
font-size:12px;
line-height:2rem;
background:#777171;
/* border-radius:8%;
*/
}
.contant-prompt .prompt div {
color:#fff;
font-weight:700;
padding-left:.3rem;
padding-right:.3rem;
}

最后,欢迎IT同事好友朋友们,互相指教,进步!

js高仿QQ消息列表左滑功能的更多相关文章

  1. 仿QQ列表左滑删除

    一直想写个仿QQ通讯列表左滑删除的效果,今天终于忙里偷闲,简单一个. 大概思路是这样的: 通过 ontouchstartontouchmoveontouchend 结合css3的平移. 不多说,直接上 ...

  2. Android 高仿QQ滑动弹出菜单标记已读、未读消息

    在上一篇博客<Android 高仿微信(QQ)滑动弹出编辑.删除菜单效果,增加下拉刷新功能>里,已经带着大家学习如何使用SwipeMenuListView这一开源库实现滑动列表弹出菜单,接 ...

  3. iOS天气动画、高仿QQ菜单、放京东APP、高仿微信、推送消息等源码

    iOS精选源码 TYCyclePagerView iOS上的一个无限循环轮播图组件 iOS高仿微信完整项目源码 想要更简单的推送消息,看本文就对了 ScrollView嵌套ScrolloView解决方 ...

  4. Android实现高仿QQ附近的人搜索展示

    本文主要实现了高仿QQ附近的人搜索展示,用到了自定义控件的方法 最终效果如下 1.下面展示列表我们可以使用ViewPager来实现(当然如果你不觉得麻烦,你也可以用HorizontalScrollVi ...

  5. 史上最简单,一步集成侧滑(删除)菜单,高仿QQ、IOS。

    重要的话 开头说,not for the RecyclerView or ListView, for the Any ViewGroup. 本控件不依赖任何父布局,不是针对 RecyclerView. ...

  6. Android 高仿QQ5.2双向側滑菜单DrawerLayout实现源代码

    Android 高仿QQ5.2双向側滑菜单DrawerLayout实现源代码 左右側滑效果图 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a ...

  7. 高仿QQ的即时通讯应用带服务端软件安装

    Android 基于xmpp协议,smack包,openfire服务端(在下面)的高仿QQ的即时通讯实现.实现了注册,登录,读取好友列表,搜索好友,添加分组,添加好友,删除好友,修改心情,两个客户端之 ...

  8. 高仿QQ即时聊天软件开发系列之二登录窗口界面

    继上一篇高仿QQ即时聊天软件开发系列之一开端之后,开始做登录窗口 废话不多说,先看效果,只有界面 可能还有一些细节地方没有做,例如那个LOGO嘛,不要在意这些细节 GIF虽短,可是这做起来真难,好吧因 ...

  9. 高仿QQ头像截取

    花费了半天时间,把 仿QQ头像截取的方法整理了下,并制作了一个demo以供大家参考,基本上实现了qq中我的资料界面上(包括背景透明化,上滑标题栏显示,下拉隐藏等)的大致效果,先上图看效果吧: 支持的功 ...

随机推荐

  1. 单片机TM4C123学习(七):I2C模块(温度传感器)

    I2C(Inter Intergrated Circuit)总线是Philips公司推出的一种用于IC器件之间连接的二线制串行扩展总线,它通过两根信号线(SDA-串行数据线:SCL-串行时钟线)在连接 ...

  2. 重签名问题:does not have a signature matching

    今天在家里电脑重签名过的apk拿到公司来用装到模拟器上,运行Robotium测试用例时,报了如下错误,原本以为是工程里的activity名称和包名写错了呢,检查了一遍发现木有错误呀.... 好吧,那我 ...

  3. sprintf()函数基本用法

    基本用法 sprintf 是个变参函数,定义如下: int sprintf( char *buffer, const char *format [, argument] ... ); sprintf的 ...

  4. 实战录 | Redis的主从服务器搭建

    <实战录>导语 云端卫士<实战录>栏目定期会向粉丝朋友们分享一些在开发运维中的经验和技巧,希望对于关注我们的朋友有所裨益.本期分享人为云端卫士安全平台工程师田全磊,将带来Red ...

  5. js-事件、正则表达式

    AddEventListener()之中有三个参数,分别是(1)事件的名称(注:不要加on,例:click才是点击事件的名称)(2)需要执行的function(){} (3)布尔类型(false表示的 ...

  6. netbeans中实体类代码的bug

    用了netbeans中实体类代码后,忽然报错: com.sun.tools.javac.code.Symbol$CompletionFailure: 找不到sun.util.logging.Platf ...

  7. hibernate cascade=CascadeType.All

    因为时间关系,我在这里测试的环境是一对多的关系里面用到的注解方式的级联,网上也有很多贴子,我也看过了,但是呢,我还是自己总结一下吧,这觉得级联是单向的,不是双向的,意思就是说,我们在设置两个类的对象之 ...

  8. Keepalived安装配置

    一.  介绍 keepalived:是一个类似于 layer3, 4 & 7 交换机制的软件,也就是我们平时说的第 3 层.第 4 层和第 7层交换. Keepalived 的作用是检测 we ...

  9. 斯坦福第四课:多变量线性回归(Linear Regression with Multiple Variables)

    4.1  多维特征 4.2  多变量梯度下降 4.3  梯度下降法实践 1-特征缩放 4.4  梯度下降法实践 2-学习率 4.5  特征和多项式回归 4.6  正规方程 4.7  正规方程及不可逆性 ...

  10. 关闭 selinux 和防火墙

    1.关闭 selinux 修改 它的配置文档 /etc/selinux/conf 修改 SELINUX=disabled 或者permissive 2. 关闭 防火墙 输入命令 systemctl d ...