1

在做公司移动端项目的时候,需要频繁选择日期和时间,在网上搜到的大部分插件都有bug存在,于是自己干脆写了一个插件出来,以应对公司项目的需求。

下面把插件源码放出来,供需要的小伙伴们复制粘贴(插件没有bug,可以放心使用,喜欢的给个赞哦(o^*^o)!!!):

插件使用方法:

HTML:

<li class="time" style="font-size:14px;">
     时间
</li>
<li class="date" style="font-size:14px;">
     日期
</li>

js:        

$(function(){
    $(".date").pickTimer({
        'pickType':'y:m:d',
        'yearSize':'30'
    });
    $(".time").pickTimer({
        'pickType':'h:m:s',
        'speed':3
    });
});

jquery.pickTimer.js

/*
* pluginName:pickTimer,
* author:yangyang2010cs@163.com
* Individual contact method:986372959(It's my QQ)
* date:2017/09/07 18:45:00
* */
;(function($,window,document,undefined){
    'use strict'; //严格模式,提高效率
    var pluginName = 'pickTimer', //定义插件的名字
        defaults = {},//定义一个默认的参数
        liH,//每一个li的高度
        $list,//滑动列表
        globalThis_launchHtml,
        pluginThis;//指代指向plugin的this
    var global = {
        options:''
    };
    function Plugin(options){ //创建构造函
        //this -- Plugin对象
        pluginThis = this;
        this.options = options;
        this.init(); //初始化
    }
    Plugin.prototype = {
        init:function(){
            //this -- Plugin对象
            var str = '<div class="pick-container touches">'+
                '<div class="row pick-m0">'+
                '<div class="col s3 center-align">'+
                '<a href="javascript:void(0)" class="pick-cancel">取消</a>'+
                '</div>'+
                '<div class="col s6 center-align pick-title">'+(this.options.pickType=='y:m:d'?'设置日期':'设置时间')+'</div>'+
                '<div class="col s3 center-align">'+
                '<a href="javascript:void(0)" class="pick-sure">确定</a>'+
                '</div>'+
                '</div>'+
                '<div class="row pick-m0">'+
                '<div class="col s4 pick-timer">'+
                    '<div class="pick-bgTop"></div>'+
                    '<ul class="list">'+
                    '</ul>'+
                    '<div class="current '+(this.options.pickType=='y:m:d'?'current-date-right':'current-time')+'"></div>'+
                    '<div class="pick-bgBottom"></div>'+
                '</div>'+
                '<div class="col s4 pick-timer">'+
                '<div class="pick-bgTop"></div>'+
                    '<ul class="list">'+
                    '</ul>'+
                    '<div class="current '+(this.options.pickType=='y:m:d'?'current-date-left current-date-right':'current-time')+'"></div>'+
                    '<div class="pick-bgBottom"></div>'+
                '</div>'+
                '<div class="col s4 pick-timer">'+
                    '<div class="pick-bgTop"></div>'+
                    '<ul class="list">'+
                    '</ul>'+
                    '<div class="current '+(this.options.pickType=='y:m:d'?'current-date-left':'')+'"></div>'+
                    '<div class="pick-bgBottom"></div>'+
                '</div>'+
                '</div>'+
                '</div>'+
                '<div class="pick-layer"></div>';
            $("body").append(str);
            $(".pick-cancel,.pick-layer").on("click",function(){
                $(".touches,.pick-layer").remove();
                $("body").unbind("touchmove"); //恢复了body的拖动事件
            });
            $(".pick-sure").on("click",function(){
                var val = '';
                $(".pick-active").each(function(){
                    if(pluginThis.options.pickType=='y:m:d'){
                        val += $(this).text()+'-';
                    } else if(pluginThis.options.pickType=='h:m:s'){
                        val += $(this).text()+':';
                    }
                });
                $(globalThis_launchHtml).html(val.substring(0,val.length-1));
                $(".touches,.pick-layer").remove();
                $("body").unbind("touchmove"); //恢复了body的拖动事件
            });
            $("body").on('touchmove',function (e){
                e.preventDefault();
            });
            this.render(); //渲染
        },
        render:function(){
            //this -- Plugin对象
            global.options = this.options;
            $list = $(".list");
            if(this.options.pickType=='h:m:s'){
                for(var h=0;h<24;h++) {
                    $list.eq(0).append("<li>" + (h >= 10 ? h : '0' + h) + "</li>")
                }
                for (var m = 0; m < 60; m++) {
                    $list.eq(1).append("<li>" + (m >= 10 ? m : '0' + m) + "</li>")
                }
                for (var s = 0; s < 60; s++) {
                    $list.eq(2).append("<li>" + (s >= 10 ? s : '0' + s) + "</li>")
                }
                liH = $list.find("li").eq(0).height();//li的高度
                var hour = new Date().getHours(),min = new Date().getMinutes(),sec = new Date().getSeconds();
                $list.eq(0).find("li").eq(hour).addClass("pick-active");//一开始默认第三行选中
                $list.eq(0).css("top",(-hour+2)*liH);
                $list.eq(1).find("li").eq(min).addClass("pick-active");//一开始默认第三行选中
                $list.eq(1).css("top",(-min+2)*liH);
                $list.eq(2).find("li").eq(sec).addClass("pick-active");//一开始默认第三行选中
                $list.eq(2).css("top",(-sec+2)*liH);
            } else if(this.options.pickType=='y:m:d'){
                var year = new Date().getFullYear(),month = new Date().getMonth();
                for(var _y=0;_y<this.options.yearSize;_y++) {
                    $list.eq(0).append("<li>" +(year-Math.floor(this.options.yearSize/2)+_y)+ "</li>")
                }
                for (var _m = 1; _m < 13; _m++) {
                    $list.eq(1).append("<li>" + (_m >= 10 ? _m : '0' + _m) + "</li>")
                }
                liH = $list.find("li").eq(0).height();//li的高度
                $list.eq(0).find("li").eq(year-$list.eq(0).find("li").eq(0).text()).addClass("pick-active");//一开始默认第三行选中
                $list.eq(0).css("top",(-(year-$list.eq(0).find("li").eq(0).text())+2)*liH);
                $list.eq(0).addClass("js_year");
                $list.eq(1).find("li").eq(month).addClass("pick-active");//一开始默认第三行选中
                $list.eq(1).css("top",(-month+2)*liH);
                $list.eq(1).addClass("js_month");
                this.createDate();
            }
            this.handleEvent(); //绑定事件
            return this;
        },
        createDate:function(){ //创建日期选择中的天数一列
            $list.eq(2).html("");
            var createDate_year = $(".js_year").find("li.pick-active").text();
            var createDate_month = $(".js_month").find("li.pick-active").text();
            if (((createDate_year % 4)==0) && ((createDate_year % 100)!=0) && createDate_month=="02"|| ((createDate_year % 400)==0) && createDate_month=="02") {
                //闰年 2月
                setDateFun(29);
            } else if(!(((createDate_year % 4)==0) && ((createDate_year % 100)!=0)) && createDate_month=="02"|| !((createDate_year % 400)==0) && createDate_month=="02"){
                //非闰年 2月
                setDateFun(28);
            } else if(createDate_month=='01'||createDate_month=='03'||createDate_month=='05'||createDate_month=='07'||createDate_month=='08'||createDate_month=='10'||createDate_month=='12'){
                setDateFun(31);
            } else if(createDate_month=='04'||createDate_month=='06'||createDate_month=='09'||createDate_month=='11'){
                setDateFun(30);
            }
            function setDateFun(len){
                var date = new Date().getDate();
                for (var _d = 1; _d <= len; _d++) {
                    $list.eq(2).append("<li>" + (_d >= 10 ? _d : '0' + _d) + "</li>")
                }
                $list.eq(2).find("li").eq(date-1).addClass("pick-active");//一开始默认第几行选中
                $list.eq(2).css("top",(-date+2+1)*liH);
                $list.eq(2).addClass("js_date");
            }
            return this;
        },
        handleEvent:function(){ //函数绑定
            //this -- Plugin对象
            $list.each(function(){
                var startY = null,//开始的pageY
                    endY = null,//结束的pageY
                    distY = null,//endY - startY
                    cTop = null,//currentTop
                    _top = null,//ul.list的top值
                    timeS = null,//滚动的开始时间
                    distT = null,//每一次滚动的时间差
                    speed = null;//速度
                var SE = null;
                var ME = null;
                function startCallBack(e){
                    //这里的this指向当前滑动的$list
                    //这里的this指向当前滑动的$list
                    if(e.originalEvent.touches){
                        SE=e.originalEvent.targetTouches[0];
                        console.log(SE)
                    }
                    startY = SE.pageY;
                    cTop = $(this).position().top;
                    timeS = new Date();
                }
                function moveCallBack(e){
                    //这里的this指向当前滑动的$list
                    if(e.originalEvent.touches){
                        ME=e.originalEvent.targetTouches[0];
                        //console.log(ME)
                    }
                    var scrollSpeed = pluginThis.options.speed || 2;
                    endY = ME.pageY;
                    distY = scrollSpeed*(endY - startY);
                    //console.log(distY);//往下滑动是正直,往上是负值
                    if(cTop+distY>88){//从顶部往下滑动
                        _top = 88;
                    } else if(cTop+distY<$(this).parent().height()-$(this).height()-88){//从底部往上滑动
                        _top = $(this).parent().height() - $(this).height()-88;
                    } else {//中间地方滑动
                        _top = cTop+distY;
                    }
                    _top = _top - _top % liH;//取整
                    $(this).css('top',_top);
                    if(_top==44){
                        $(this).find("li").eq(1).addClass("pick-active").siblings().removeClass("pick-active");
                    } else if(_top==88){
                        $(this).find("li").eq(0).addClass("pick-active").siblings().removeClass("pick-active");
                    } else {
                        $(this).find("li").eq(Math.abs(_top/liH)+2).addClass("pick-active").siblings().removeClass("pick-active");
                    }
                }
                function endCallBack(e){
                    //这里的this指向当前滑动的$list
                    var $this = $(this);
                    var dir = distY < 0 ? 1 : -1;//方向 上移为1,下移为-1
                    distT = new Date() - timeS;
                    speed = Math.abs(distY / distT);//单位px/ms
                    if(speed>0.6) {
                        /*alert(1)*/
                        if (dir == 1 && Math.abs(_top / liH) + 3 == $(this).find('li').length) { //手指向上滑动
                            if($this.attr("class")!="list js_date" && pluginThis.options.pickType=='y:m:d'){
                                //判断闰年下,2月份天数的展示及其它月份天数的展示
                                pluginThis.createDate();
                            }
                            return;//到底了,不能滑了
                        } else if(dir==-1 && _top==88){ //手指向下滑动
                            if($this.attr("class")!="list js_date" && pluginThis.options.pickType=='y:m:d'){
                                //判断闰年下,2月份天数的展示及其它月份天数的展示
                                pluginThis.createDate();
                            }
                            return;//到顶了,不能滑了
                        }
                    }
                    setTimeout(function(){
                        $this.css("top",_top);
                        if(_top==44){
                            $(this).find("li").eq(1).addClass("pick-active").siblings().removeClass("pick-active");
                        } else if(_top==88){
                            $(this).find("li").eq(0).addClass("pick-active").siblings().removeClass("pick-active");
                        } else {
                            $(this).find("li").eq(Math.abs(_top/liH)+2).addClass("pick-active").siblings().removeClass("pick-active");
                        }
                        if($this.attr("class")!="list js_date" && pluginThis.options.pickType=='y:m:d'){
                            //判断闰年下,2月份天数的展示及其它月份天数的展示
                            pluginThis.createDate();
                        }
                    },50);
                }
                $(this).off('touchstart').on('touchstart',startCallBack); //下滑开始 这里的this指向plugin对象
                $(this).off('touchmove').on('touchmove',moveCallBack); //滑动的时候 这里的this指向plugin对象
                $(this).off('touchend').on('touchend',endCallBack); //滑动完了 这里的this指向plugin对象
            })
        }
    };
    $.fn[pluginName] = function(options){
        //do someting
        $(this).click(function(){
                globalThis_launchHtml = this;
                new Plugin(options);
        });
        return this;//返回调用插件的对象,以便支持链式调用
    }
})(jQuery,window,document);

jquery.pickTimer.css

.pick-container ul{
    margin:0;
    padding:0;
}
.pick-container ul,.pick-container li{
    list-style: none;
}
.pick-container a{
    text-decoration: none;
}
/*materialize*/
.pick-container *{-webkit-tap-highlight-color:transparent;}
.pick-container {
    position:fixed;
    z-index:99999999;
    left:0;
    bottom:0;
    width:100vw;
    background:#fff;
    margin: 0 auto;
    max-width: 1280px;
}
*, *:before, *:after {
    -webkit-box-sizing: inherit;
    box-sizing: inherit;
}
.pick-m0 {
    margin: 0;
}
.row:after {
    content: "";
    display: table;
    clear: both;
}
.row .col {
    float: left;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    padding: 0 .75rem;
    min-height: 1px;
}
.row .col.s3 {
    width: 25%;
    margin-left: auto;
    left: auto;
    right: auto;
}
.row .col.s4 {
    width: 33.33333333333%;
    margin-left: auto;
    left: auto;
    right: auto;
}
.row .col.s6 {
    width: 50%;
    margin-left: auto;
    left: auto;
    right: auto;
}
.center, .center-align {
    text-align: center;
}
/*layer*/
.pick-layer{
    position: fixed;
    top:0;
    bottom:0;
    left:0;
    right:0;
    z-index:99999998;
    background:rgba(0,0,0,0.4);
}
/*pick-timer*/
.pick-timer{
    overflow: hidden;
    position:relative;
    border-top:1px solid #eee;
    height:220px;
}
.pick-timer .list{
    position:absolute;
    top:0;
    left:0;
    z-index:2;
    width:100%;
    transition:top .4s ease-out;
}
.pick-timer .list li{
    height:44px;
    line-height:44px;
    text-align:center;
    color:#666;
    font-size:14px;
    transition:all .1s ease-out;
}
.pick-timer .list li.pick-active{
    font-size:20px;
    color:#e02222;
}
.pick-timer .current{
    position:absolute;
    top:88px;
    left:0;
    z-index:1;
    border-top:1px solid #e02222;
    border-bottom:1px solid #e02222;
    width:100%;
    height:44px;
    background:#fff;
}
/*pick-head*/
.pick-cancel{
    display: block;
    font-size:14px;
    color:#666;
    height:40px;
    line-height:40px;
}
.pick-sure{
    display: block;
    font-size:14px;
    color:#e02222;
    height:40px;
    line-height:40px;
}
.pick-title{
    font-size:14px;
    color:#666;
    height:40px;
    line-height:40px;
}
/*current-time*/
.current-time:after{
    content:':';
    font-size: 14px;
    text-align: center;
    line-height: 44px;
    color: #666;
    position: absolute;
    top:-2px;
    right:0;
}
.current-date-right:after{
    content:'.';
    color:transparent;
    width:5px;
    border-top:1px solid #999;
    position: absolute;
    top:20px;
    right:0;
}
.current-date-left:before{
    content:'.';
    color:transparent;
    width:5px;
    border-top:1px solid #999;
    position: absolute;
    top:20px;
    left:0;
}
/**/
.pick-bgTop{
    position:absolute;
    top:0;
    left:0;
    width:100%;
    height:88px;
    /*background: linear-gradient(#fff 0%, rgba(255, 255, 255, .85)45%, rgba(255, 255, 255, .6) 75%, rgba(255, 255, 255, .4) 100%);*/
    background: -webkit-gradient(linear, left top, left bottom, from(#efefef),to(rgba(255, 255, 255, .1)));
    z-index:1;
}
.pick-bgBottom{
    position:absolute;
    bottom:0;
    left:0;
    width:100%;
    height:87px;
    /*background: linear-gradient(rgba(255, 255, 255, .4) 0%, rgba(255, 255, 255, .6)25%, rgba(255, 255, 255, .85) 65%, #fff 100%);*/
    background: -webkit-gradient(linear, left top, left bottom, from(rgba(255, 255, 255, .1)),to(#efefef));
    z-index:1;
}

特别注意:

由于在网上找到的插件都是用<input type="text" class="time"/>来触发插件,但是使用input,在ios上会出现光标和系统自带的底部带有‘完成’的确认横条,这样很难看,虽然有办法解决,但是麻烦。于是我在插件里没有使用input的value属性来获取值,而是使用了除input元素外的其它任何标签,代码原理中使用jquery中text()方法来写值。在插件使用方法中就可以看出来,现在就回到页面顶部看一看吧,我用的是<li></li>,你也可以用其他的标签。

clipboard.png

clipboard.png


CodeMan
1.4k 声望58 粉丝

《伤害》