JavaScript 日期选择器

效果图如下:



代码:

/**
 * Created by SharkMarine on 2017/10/31
 */
(function () {
    var item_default;
    var selectDate;
    var selectNode;//选中的年月日用于滚动
    var curMonthDayCount;//某年某月有多少天
    var preTouch;
    //==========立体效果参数============begin====
    var ITEM_SPACE_Y = 40;//子项之间的y间距
    var ITEM_SCALE_Y = 0.4;//scaleY
    var ITEM_POS_X = 10;//x坐标的缩进
    var ITEM_SKEW_X = 40;//倾斜度
    var ITEM_OPACITY = 0.5;//透明度
    //==========立体效果参数============begin====
    DatePicker = cc.Layer.extend({
        daySpace: 0,
        jsBind: {
            _event: {
                updateGuildInfo: function (data) {
                    var guildid = data.guildid;
                    // 玩家被踢出群删除此界面
                    if (guildid == jsclient.datepicker.guildid) {
                        if (jsclient.datepicker) {
                            jsclient.datepicker.removeFromParent(true);
                            jsclient.datepicker = null;
                        }
                    }
                }
            },
            block: {
                _layout: [[1, 1], [0.5, 0.5], [0, 0], true]
            },
            back: {
                _layout: [[911 / 1280, 0], [0.5, 0.45], [0, 0]],
                close: {
                    _click: function (btn) {
                        selectNode = null;
                        jsclient.datepicker.removeFromParent();
                        delete jsclient.datepicker;
                    }
                },
                btn_sure: {
                    _click: function (btn) {
                        if (jsclient.datepicker) {
                            var pDestString = jsclient.datepicker.getSelectDate();
                            // 把日期文字写到按钮上
                            if (jsclient.datepicker.callback) {
                                jsclient.datepicker.callback(pDestString);
                            }
                            jsclient.datepicker.removeFromParent();
                            delete jsclient.datepicker;
                        }
                    }
                },
                item_default: {
                    _visible: false,
                    _run: function () {
                        this.ignoreContentAdaptWithSize(true);
                        item_default = this;
                    }
                },
                Panel: {
                    _run: function () {
                        var children = this.getChildren();
                        for (var i = 0; i < children.length; i++) {
                            var pChild = children[i];
                            if (pChild.getName() == "year" || pChild.getName() == "month" || pChild.getName() == "day") {
                                pChild.addTouchEventListener(function (sender, type) {
                                    switch (type) {
                                        case ccui.Widget.TOUCH_BEGAN:
                                        case ccui.Widget.TOUCH_MOVED:
                                            selectNode = sender;
                                            break;
                                        case ccui.Widget.TOUCH_ENDED:
                                        case ccui.Widget.TOUCH_CANCELED:
                                            selectNode = null;
                                            break;
                                    }
                                }, pChild);
                            }
                        }
                    }
                }
            }
        },
        ctor: function (callback, guildid) {
            this._super();
            if (jsclient.datepicker) {
                jsclient.datepicker.removeFromParent();
            }
            selectNode = null;
            jsclient.datepicker = this;
            jsclient.datepicker.guildid = guildid;
            jsclient.datepicker.callback = callback;
            var jNode = ccs.load("res/DatePicker.json");
            jsclient.datepicker.jNode = jNode.node;
            ConnectUI2Logic(jNode.node, this.jsBind);
            this.addChild(jNode.node);

        },
        onEnter: function () {
            this._super();
            //this.scheduleUpdate();
            cc.eventManager.addListener(jsclient.datepicker.getTouchListener(this), -1);
            //初始化
            this.initScrollItems();
        },
        initScrollItems: function () {
            var Panel = getChildByNameOverWrite(this.jNode, "Panel");
            var year = Panel.getChildByName("year");
            var month = Panel.getChildByName("month");
            var day = Panel.getChildByName("day");
            initScrollItem(year);
            initScrollItem(month);
            initScrollItem(day);
            selectDate = jsclient.datepicker.getCurrentDate();
            function initScrollItem(target) {
                var curDate = new Date();
                var suffix;
                var pName = target.getName();
                var suffixIndex = -1;
                var date;
                switch (pName) {
                    case "year":
                        suffix = "年";
                        suffixIndex = 0;
                        date = curDate.getFullYear();
                        break;
                    case "month":
                        suffix = "月";
                        suffixIndex = 1;
                        date = curDate.getMonth() + 1;
                        break;
                    case "day":
                        suffix = "日";
                        suffixIndex = 2;
                        date = curDate.getDate();
                        //date = jsclient.datepicker.getPreDate(-8);
                        break;
                }
                // 刷新当前月的天数
                if (suffixIndex == 2) {
                    curMonthDayCount = jsclient.datepicker.getDayNumForMonth(curDate.getFullYear(),curDate.getMonth()+1);
                }
                var pSize = target.getContentSize();
                //默认初始化8个元素
                for (var i = 8; i >= 0; i--) {
                    var pItem = item_default.clone();
                    pItem.setName("item_" + i);
                    var pText = pItem.getChildByName("text");
                    var pTag = date + i - 4;
                    pText.setString(date + i - 4 + suffix);
                    // 验证 月 和 日的合法性,不能为负数
                    if (suffixIndex == 1) {
                        if (pTag > 12) {
                            pTag = pTag % 12;
                            pText.setString(pTag + suffix);
                        }
                        else if (pTag <= 0) {
                            pTag = 12 - Math.abs(pTag);
                            pText.setString(pTag + suffix);
                        }
                    }
                    else if (suffixIndex == 2) {
                        if (pTag > curMonthDayCount) {
                            pTag = pTag % curMonthDayCount;
                            pText.setString(pTag + suffix);
                        }
                        else if (pTag <= 0) {
                            pTag = curMonthDayCount - Math.abs(pTag);
                            pText.setString(pTag + suffix);
                        }
                    }
                    pText.setTag(pTag);
                    pItem.setTag(i);
                    pItem.visible = true;
                    pItem.setPositionY((i - 4) * ITEM_SPACE_Y + pSize.height / 2);
                    jsclient.datepicker.setItemCommonAttribute(pSize, pItem, suffixIndex);
                    if (i == 4) {
                        pText.setColor(cc.color(146, 78, 42));
                    }
                    else {
                        pText.setColor(cc.color(229, 211, 173));
                    }
                    target.addChild(pItem);
                }
            }
        },
        setItemCommonAttribute: function (pSize, pItem, suffixIndex) {
            var topY = pSize.height + ITEM_SPACE_Y;
            var bottomY = -ITEM_SPACE_Y;
            var pText = pItem.getChildByName("text");
            var delta = Math.abs(pItem.getPositionY() - pSize.height / 2) / (topY - pSize.height / 2);
            pItem.setScaleY(1 - ITEM_SCALE_Y * delta);
            pText.setOpacity(255 * (1 - ITEM_OPACITY * delta));
            if (suffixIndex == 0) {
                pText.setTextHorizontalAlignment(cc.TEXT_ALIGNMENT_LEFT);
                pItem.setPositionX(pSize.width / 2 + ITEM_POS_X * delta);
                pItem.setSkewX(-ITEM_SKEW_X / 2 + ITEM_SKEW_X * (pItem.getPositionY() - bottomY) / (topY - bottomY));
            }
            else if (suffixIndex == 1) {
                pItem.setPositionX(pSize.width / 2);
                pText.setTextHorizontalAlignment(cc.TEXT_ALIGNMENT_CENTER);
            }
            else if (suffixIndex == 2) {
                pItem.setPositionX(pSize.width / 2 - (ITEM_POS_X) * delta);
                pText.setTextHorizontalAlignment(cc.TEXT_ALIGNMENT_RIGHT);
            }
        },
        adaptItems: function (target, spaceY, isEnd) {
            if (!target) return;
            var pSize = target.getContentSize();
            var topY = pSize.height + ITEM_SPACE_Y;
            var bottomY = -ITEM_SPACE_Y;
            var children = target.getChildren();
            var selectNode = null;
            var suffix;
            var pName = target.getName();
            var suffixIndex = -1;
            switch (pName) {
                case "year":
                    suffix = "年";
                    suffixIndex = 0;
                    break;
                case "month":
                    suffix = "月";
                    suffixIndex = 1;
                    break;
                case "day":
                    suffix = "日";
                    suffixIndex = 2;
                    break;
            }

            for (var i = children.length - 1; i >= 0; i--) {
                var pItem = children[i];
                var pText = pItem.getChildByName("text");
                var targetPY = pItem.getPositionY() + spaceY;
                if (targetPY > topY) {
                    targetPY = (bottomY + (targetPY - topY));
                    var preItem = target.getChildByTag(((pItem.getTag() + 1) % children.length));
                    var pTextTag = preItem.getChildByName("text").getTag() - 1;
                    if (suffixIndex == 1) {
                        // 月份判断
                        if (pTextTag == 0) {
                            pTextTag = 12;
                        }
                    }
                    else if (suffixIndex == 2) {
                        if (pTextTag <= 0) {
                            pTextTag = curMonthDayCount;
                        }
                    }
                    pText.setString(pTextTag + suffix);
                    pText.setTag(pTextTag);
                }
                else if (targetPY < bottomY) {
                    targetPY = topY + (targetPY - bottomY);
                    var preItem = target.getChildByTag((pItem.getTag() + children.length - 1) % children.length);
                    var pTextTag = preItem.getChildByName("text").getTag() + 1;
                    if (suffixIndex == 1) {
                        // 月份判断
                        if (pTextTag > 12) {
                            pTextTag = 1;
                        }
                    }
                    else if (suffixIndex == 2) {
                        if (pTextTag > curMonthDayCount) {
                            pTextTag = 1;
                        }
                    }
                    pText.setString(pTextTag + suffix);
                    pText.setTag(pTextTag);
                }
                pItem.setPositionY(targetPY);
                if (isEnd == true) {
                    if (!selectNode) {
                        selectNode = pItem;
                    }
                    else {
                        if (Math.abs(targetPY - pSize.height / 2) < Math.abs(selectNode.getPositionY() - pSize.height / 2)) {
                            selectNode = pItem;
                        }
                    }
                }
                jsclient.datepicker.setItemCommonAttribute(pSize, pItem, suffixIndex);
            }
            if (isEnd && selectNode) {
                var isMonthDayCountChanged = false;
                var pSpaceY = pSize.height / 2 - selectNode.getPositionY();
                // 设置色值
                for (var i = 0; i < children.length; i++) {
                    var pItem = children[i];
                    var pText = pItem.getChildByName("text");
                    if (pItem.getName() == selectNode.getName()) {
                        pText.setColor(cc.color(146, 78, 42));
                        // 更新选中的年月日
                        selectDate[suffixIndex] = pText.getTag();
                        //当年和月发生变化时刷新day的列表项
                        if (suffixIndex < 2) {
                            // 判断对应年月下对应的当月的天数
                            var pMonthDayCount = curMonthDayCount;
                            var curDate = new Date(selectDate[0], selectDate[1], 0);
                            pMonthDayCount = jsclient.datepicker.getDayNumForMonth(curDate.getFullYear(), curDate.getMonth()+1);
                            // 天数不一样
                            if (pMonthDayCount != curMonthDayCount) {
                                isMonthDayCountChanged = true;
                                curMonthDayCount = pMonthDayCount;
                            }
                        }
                    }
                    else {
                        pText.setColor(cc.color(229, 211, 173));
                    }
                }
                // 改变年或月后,重置天数显示
                if (suffixIndex < 2 && isMonthDayCountChanged) {
                    var panelDay = getChildByNameOverWrite(target.getParent(), "day");
                    var pDayChildren = panelDay.getChildren();
                    var selectIndexForDay = null;
                    for (var i = 0; i < pDayChildren.length; i++) {
                        var pItem = pDayChildren[i];
                        var pText = pItem.getChildByName("text");
                        if (pText.getTag() == selectDate[2]) {
                            selectIndexForDay = pItem.getTag();
                            break;
                        }
                    }
                    if (selectDate[2] > curMonthDayCount) {
                        selectDate[2] = curMonthDayCount;
                    }
                    for (var i = 4; i >= -4; i--) {
                        var pIndex = (9 + i + selectIndexForDay) % 9;
                        var pItem = panelDay.getChildByTag(pIndex);
                        //var pName =pItem.getName();
                        var pText = pItem.getChildByName("text");
                        var pTag = selectDate[2] + i;
                        pText.setString(pTag + "日");
                        if (pTag > curMonthDayCount) {
                            pTag = pTag % curMonthDayCount;
                        }
                        else if (pTag <= 0) {
                            pTag = curMonthDayCount - Math.abs(pTag);
                        }
                        pText.setString(pTag + "日");
                        pText.setTag(pTag);
                    }
                }
                this.adaptItems(target, pSpaceY);
            }
        },
        getCurrentDate: function () {
            var now = new Date();
            var year = now.getFullYear();       //年
            var month = now.getMonth() + 1;     //月
            var day = now.getDate();            //日
            var date = [year, month, day];
            return date;
        },
        getDayNumForMonth: function (year, month) {
            var curDate = new Date(year, month, 0);
            return curDate.getDate();
        },
        _handlePressLogic: function (touch) {
            this._startRecordSlidAction();
            this._bePressed = true;
        },
        _handleMoveLogic: function (spaceY, selectNode) {
            if (!selectNode) {
                return;
            }
            this.adaptItems(selectNode, spaceY);
        },
        _handleReleaseLogic: function (touch) {
            this._endRecordSlidAction();
            this._bePressed = false;
        },
        _startRecordSlidAction: function () {
            if (this._autoScroll)
                this._stopAutoScrollChildren();
            this._slidTime = 0.0;
        },
        _endRecordSlidAction: function () {
            if (!this._checkNeedBounce() && this.inertiaScrollEnabled) {
                if (this._slidTime <= 0.016)
                    return;
                var totalDis = 0, dir;
                var touchEndPositionInNodeSpace = this.convertToNodeSpace(this._touchEndPosition);
                var touchBeganPositionInNodeSpace = this.convertToNodeSpace(this._touchBeganPosition);
                switch (this.direction) {
                    case ccui.ScrollView.DIR_VERTICAL :
                        totalDis = touchEndPositionInNodeSpace.y - touchBeganPositionInNodeSpace.y;
                        dir = (totalDis < 0) ? ccui.ScrollView.SCROLLDIR_DOWN : ccui.ScrollView.SCROLLDIR_UP;
                        break;
                    case ccui.ScrollView.DIR_HORIZONTAL:
                        totalDis = touchEndPositionInNodeSpace.x - touchBeganPositionInNodeSpace.x;
                        dir = totalDis < 0 ? ccui.ScrollView.SCROLLDIR_LEFT : ccui.ScrollView.SCROLLDIR_RIGHT;
                        break;
                    case ccui.ScrollView.DIR_BOTH :
                        var subVector = cc.pSub(touchEndPositionInNodeSpace, touchBeganPositionInNodeSpace);
                        totalDis = cc.pLength(subVector);
                        dir = cc.pNormalize(subVector);
                        break;
                    default:
                        dir = cc.p(0, 0);
                        break;
                }
                var orSpeed = Math.min(Math.abs(totalDis) / (this._slidTime), ccui.ScrollView.AUTO_SCROLL_MAX_SPEED);
                this._startAutoScrollChildrenWithOriginalSpeed(dir, orSpeed, true, -1000);
                this._slidTime = 0;
            }
        },
        update: function (dt) {
            if (this._autoScroll)
                this._autoScrollChildren(dt);
            if (this._bouncing)
                this._bounceChildren(dt);
            this._recordSlidTime(dt);
        },
        _stopAutoScrollChildren: function () {
            this._autoScroll = false;
            this._autoScrollOriginalSpeed = 0;
            this._autoScrollAddUpTime = 0;
        },
        _recordSlidTime: function (dt) {
            if (this._bePressed)
                this._slidTime += dt;
        },
        _autoScrollChildren: function (dt) {
            var lastTime = this._autoScrollAddUpTime;
            this._autoScrollAddUpTime += dt;
            if (this._isAutoScrollSpeedAttenuated) {
                var nowSpeed = this._autoScrollOriginalSpeed + this._autoScrollAcceleration * this._autoScrollAddUpTime;
                if (nowSpeed <= 0) {
                    this._stopAutoScrollChildren();
                    this._checkNeedBounce();
                } else {
                    var timeParam = lastTime * 2 + dt;
                    var offset = (this._autoScrollOriginalSpeed + this._autoScrollAcceleration * timeParam * 0.5) * dt;
                    var offsetX = offset * this._autoScrollDir.x;
                    var offsetY = offset * this._autoScrollDir.y;
                    if (!this._scrollChildren(offsetX, offsetY)) {
                        this._stopAutoScrollChildren();
                        this._checkNeedBounce();
                    }
                }
            } else {
                if (this._needCheckAutoScrollDestination) {
                    var xOffset = this._autoScrollDir.x * dt * this._autoScrollOriginalSpeed;
                    var yOffset = this._autoScrollDir.y * dt * this._autoScrollOriginalSpeed;
                    var notDone = this._checkCustomScrollDestination(xOffset, yOffset);
                    var scrollCheck = this._scrollChildren(xOffset, yOffset);
                    if (!notDone || !scrollCheck) {
                        this._stopAutoScrollChildren();
                        this._checkNeedBounce();
                    }
                } else {
                    if (!this._scrollChildren(this._autoScrollDir.x * dt * this._autoScrollOriginalSpeed,
                            this._autoScrollDir.y * dt * this._autoScrollOriginalSpeed)) {
                        this._stopAutoScrollChildren();
                        this._checkNeedBounce();
                    }
                }
            }
        },
        getTouchListener: function (target) {
            return {
                event: cc.EventListener.TOUCH_ONE_BY_ONE,
                swallowTouches: false,
                status: null,
                onTouchBegan: function (touch, event) {
                    if (item_default && jsclient.datepicker) {
                        jsclient.datepicker._handlePressLogic(touch);
                        preTouch = touch.getLocation();
                    }
                    return true;
                },
                onTouchMoved: function (touch, event) {
                    if (selectNode && preTouch) {
                        var spaceY = cc.pSub(touch.getLocation(), preTouch);
                        preTouch = touch.getLocation();
                        jsclient.datepicker.adaptItems(selectNode, spaceY.y);
                    }
                },
                onTouchEnded: function (touch, event) {
                    if (selectNode && preTouch) {
                        var spaceY = cc.pSub(touch.getLocation(), preTouch);
                        jsclient.datepicker.adaptItems(selectNode, spaceY.y, true);
                        preTouch = null;
                    }
                },
                onTouchCancelled: function (touch, event) {
                }
            };
        },
        getSelectDate: function () {
            var isValidate = true;
            if (isNaN(selectDate[0])) {
                isValidate = false;
            }
            if (isNaN(selectDate[1]) || selectDate[1] > 12 || selectDate[1] < 1) {
                isValidate = false;
            }
            if (isNaN(selectDate[2]) || selectDate[2] > curMonthDayCount || selectDate[2] < 1) {
                isValidate = false;
            }
            if (!isValidate) {
                selectDate = this.getCurrentDate();
            }
            // 拼字符串
            var pDestString = "" + selectDate[0];
            if (selectDate[1] < 10) {
                pDestString += "0" + selectDate[1];
            }
            else {
                pDestString += selectDate[1];
            }
            if (selectDate[2] < 10) {
                pDestString += "0" + selectDate[2];
            }
            else {
                pDestString += selectDate[2];
            }
            return pDestString;
        }
    });
})();

注意问题:JavaScript的setMonth

如果使用不好会导致显示的日期不对,比如说2017-10-31,可能没有31日等。

问题原因:比如说curDate 为:2017-10-31

curDate.setMonth(curDate.getMonth() + 1);
curMonthDayCount = jsclient.datepicker.getDayNumForMonth(curDate);
因为今天是10-31,
curDate.setMonth(curDate.getMonth() + 1);
后变为11-31,因为11月没有31号,所以日期变为12-1,导致月份直接+2。

最终导致以下方法获取的当前月的天数错误(实际上获取的是11月份的天数),同理setMonth(*,0);会导致直接跳转到上个月的最大天数,和setMonth(*,31);一样存在边界问题。

getDayNumForMonth: function (date) {
    var curDate = new Date(date);
    /* 获取当前月份 */
    var curMonth = curDate.getMonth();
    /*  生成实际的月份: 由于curMonth会比实际月份小1, 故需加1 */
    curDate.setMonth(curMonth);
    /* 将日期设置为0, 这里为什么要这样设置, 我不知道原因, 这是从网上学来的 */
    curDate.setDate(0);
    /* 返回当月的天数 */
    return curDate.getDate();
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值