JS实用控件——可滑动列表项

有时候我们在一个list中要为列表项添加左右滑动的效果,通过滑动出来的按钮实现一些点击事件,这时候就可以用到本文所介绍的插件了。

照例,先上效果图:


插件效果图

我觉得这个效果还是挺高频且实用的,奈何weui里面没有这个扩展,只能自己在网上搜索并改进了。为了方便使用,我已经把左右滑动效果封装成了一个jquery插件了,读者也可以根据需要修改其代码做更多的扩展。

1、列表项html
先贴一下列表项的html代码:

<a href="#" class="weui-media-box weui-media-box_appmsg swipte_item">
    <div class="weui-media-box__hd">
        <img class="weui-media-box__thumb" src="thumbnail.png">
    </div>
    <div class="weui-media-box__bd">
        <h4 class="weui-media-box__title"></h4>
        <p class="weui-media-box__desc"></p>
    </div>
    <li class="weui-swiped-btn weui-swiped-btn_warn swipe_btn">拒接</li>
    <li class="weui-swiped-btn accept_btn">接单</li>
</a>

其中,两个li标签的class属性可以自定义,后续生成滑动实例要用到,还有,我用的是weui,写出来是如上的效果,读者最好根据需求自行制作控件。

2、列表项css
随后是css代码:

.weui-swiped-btn.weui-swiped-btn_warn.swipe_btn {
    color: white;
    position: absolute;
    right: -67px;
    width: 35px;
    text-align: center;
    height: 70px;
    line-height: 70px;
}

.weui-swiped-btn.accept_btn {
    color: white;
    background: #1AAD19;
    position: absolute;
    left: -67px;
    width: 35px;
    text-align: center;
    height: 70px;
    line-height: 70px;
}

读者根据自己的需求修改就好了,这里面有个问题,就是left、right的偏移和width不一样,我暂时没找出问题根源,只能在插件里通过增加滑动偏移来抵消掉负偏移,不知道哪位大神能指导一下。

3、滑动插件js代码
借鉴前人代码基础上,已经封装成了JQuery代码,能实现左右双向的滑动:

/* * 
 * @brief 列表项左滑右滑功能创建
 *        使用方法:$('.itemWipe').touchWipe({itemBtn: '.item-button'});
 * @param itemWipe  条目样式名
 *        itemBtn   滑动后出现的按钮样式名(左右按钮大小应一致,传入任一个即可)
 * @return 带滑动效果的列表项
 * */
(function ($) {
    $.fn.touchWipe = function (option) {
        var defaults = {
            itemBtn: '.item-delete', //删除元素
        };
        var opts = $.extend({}, defaults, option); //配置选项
        var btnWidth = $(opts.itemBtn).width() + 32;  //此处有文章中说的问题,望指导

        var initX; //触摸位置X
        var initY; //触摸位置Y
        var moveX; //滑动时的位置X
        var moveY; //滑动时的位置Y
        var X = 0; //移动距离X
        var Y = 0; //移动距离Y
        var flagX = 0; //是否是左右滑动 0为初始,1为左右,2为上下,在move中设置,在end中归零
        var objX = 0; //目标对象位置

        $(this).on('touchstart', function (event) {
            //console.log('start..');
            var obj = this;
            initX = event.targetTouches[0].pageX;
            initY = event.targetTouches[0].pageY;
            //console.log(initX + ':' + initY);
            objX = (obj.style.WebkitTransform.replace(/translateX\(/g, "").replace(/px\)/g, "")) * 1;
            //console.log(objX);
            if (objX == 0) {
                $(this).on('touchmove', function (event) {
                    // 判断滑动方向,X轴阻止默认事件,Y轴跳出使用浏览器默认
                    if (flagX == 0) {
                        setScrollX(event);
                        return;
                    } else if (flagX == 1) {
                        event.preventDefault();
                    } else {
                        return;
                    }

                    var obj = this;
                    moveX = event.targetTouches[0].pageX;
                    X = moveX - initX;
                    if (X >= 0) {
                        var l = Math.abs(X);
                        obj.style.WebkitTransform = "translateX(" + l + "px)";
                        if (l > btnWidth) {
                            l = btnWidth;
                            obj.style.WebkitTransform = "translateX(" + l + "px)";
                        }
                    } else if (X < 0) {
                        var l = Math.abs(X);
                        obj.style.WebkitTransform = "translateX(" + -l + "px)";
                        if (l > btnWidth) {
                            l = btnWidth;
                            obj.style.WebkitTransform = "translateX(" + -l + "px)";
                        }
                    }
                });
            } else if (objX < 0) {
                $(this).on('touchmove', function (event) {
                    // 判断滑动方向,X轴阻止默认事件,Y轴跳出使用浏览器默认
                    if (flagX == 0) {
                        setScrollX(event);
                        return;
                    } else if (flagX == 1) {
                        event.preventDefault();
                    } else {
                        return;
                    }

                    var obj = this;
                    moveX = event.targetTouches[0].pageX;
                    X = moveX - initX;
                    if (X >= 0) {
                        var r = -btnWidth + 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(" + -btnWidth + "px)";
                    }
                });
            } else {
                $(this).on('touchmove', function (event) {
                    // 判断滑动方向,X轴阻止默认事件,Y轴跳出使用浏览器默认
                    if (flagX == 0) {
                        setScrollX(event);
                        return;
                    } else if (flagX == 1) {
                        event.preventDefault();
                    } else {
                        return;
                    }

                    var obj = this;
                    moveX = event.targetTouches[0].pageX;
                    X = moveX - initX;
                    if (X <= 0) {
                        var r = btnWidth + 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(" + btnWidth + "px)";
                    }
                });
            }
        })

        //结束时判断,并自动滑动到底或返回
        $(this).on('touchend', function (event) {
            var obj = this;
            objX = (obj.style.WebkitTransform.replace(/translateX\(/g, "").replace(/px\)/g, "")) * 1;
            if (objX > -btnWidth / 2 && objX <= 0) {
                obj.style.transition = "all 0.2s";
                obj.style.WebkitTransform = "translateX(" + 0 + "px)";
                obj.style.transition = "all 0";
                objX = 0;
            } else if (objX > btnWidth / 2) {
                obj.style.transition = "all 0.2s";
                obj.style.WebkitTransform = "translateX(" + btnWidth + "px)";
                obj.style.transition = "all 0";
            } else if (objX < btnWidth / 2 && objX > 0) {
                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(" + -btnWidth + "px)";
                obj.style.transition = "all 0";
                objX = -btnWidth;
            }
            flagX = 0;
        })

        //设置滑动方向
        function setScrollX(event) {
            moveX = event.targetTouches[0].pageX;
            moveY = event.targetTouches[0].pageY;
            X = moveX - initX;
            Y = moveY - initY;

            if (Math.abs(X) > Math.abs(Y)) {
                flagX = 1;
            } else {
                flagX = 2;
            }
            return flagX;
        }

        //链式返回
        return this;
    };

})(jQuery);

接下来,我会其中关键的地方和思路解释清楚,具体内容就需要读者自己理解了:

1、获得首次点击时的像素点(x,y)坐标值,并通过WebkitTransform获得当前列表项偏移的像素(objX等于0说明没有偏移,大于0说明向右偏移了,小于0说明向左偏移了)。

2、touchmove事件触发后,获得当前的手指点住的像素点(x,y)坐标,通过与初始坐标相减,获得手指滑动的方向(变量X大于0是右滑,小于0是左滑)。

3、随后,判断当前x轴的偏移量,当超过按钮一半是自动滑动到底,小于一半是返回。

4、最后,在你的js代码中,通过$('.itemWipe').touchWipe({itemBtn: '.item-button'});即可为指定html标签绑定此功能。

以上。

github传送地址:https://github.com/JunJieDing666/YouZhiGou

若有错误烦请指出,有地方不理解欢迎讨论。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352