js高仿QQ消息列表左滑功能

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js高仿QQ消息列表左滑功能相关的知识,希望对你有一定的参考价值。

  该组件,主要功能类似于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消息列表左滑功能的主要内容,如果未能解决你的问题,请参考以下文章

推荐一个高仿微信的项目 有点屌!!

Android高级控件——自定义ListView高仿一个QQ可拖拽列表的实现

基于 Vue.js 的消息气泡插件

安卓高仿IOS按钮

Android 使用HorizontalScrollView实现RecyclerView左滑删除的功能

Android 使用HorizontalScrollView实现RecyclerView左滑删除的功能