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

时间:2024-04-08 10:29:04

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

照例,先上效果图:

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

                                                                                              插件效果图

我觉得这个效果还是挺高频且实用的,奈何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

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