月历切换效果

前端入坑纪 25

上个礼拜天就想发的新文,一直到今天总算完成了。因为这回写的东西真的有点多啊!
要多多注解才行!

简洁月历

OK,first things first!项目链接

HTML 结构
    <div id="cldrWrp" class="cldrWrp">
        <div id="yearWrp">2017</div>
        <div class="clear">
            <a id="ltArr" class="arrs" href="javascript:;"></a>
            <div class="lunaName" data-mouthNum="6">
                <h2>六月</h2>
                <h3>June</h3>
            </div>
            <a id="rtArr" class="arrs" href="javascript:;"></a>
        </div>
        <div class="cldrBody">
            <div class="clear">
                <span>日</span>
                <span>一</span>
                <span>二</span>
                <span>三</span>
                <span>四</span>
                <span>五</span>
                <span>六</span>
            </div>
            <ul id="datesWrp" class="clear">

            </ul>
        </div>
        <div id="yearList">

        </div>
    </div>

html的布局上没啥特别难的,用到最多的就是浮动布局,比如每个日期的li标签都是左浮动的,然后算好宽度和对应的margin

CSS 结构
        body {
            background: #fff;
        }
        
        * {
            margin: 0;
            padding: 0
        }
        
        a {
            color: #333;
            text-decoration: none;
        }
        
        img {
            border: none;
        }
        
        .clear::after {
            content: "";
            display: table;
            clear: both
        }
        
        ul,
        li {
            list-style: none;
        }
        
        .cldrWrp {
            line-height: 35px;
            text-align: center;
            width: 100%;
            margin: 20px 0 0;
            /*box-shadow: 0 0 8px #cfcfcf;*/
            color: #666
        }
        
        #yearWrp {
            height: 40px;
            line-height: 40px;
            font-size: 20px;
        }
        
        .cldrBody span,
        .cldrBody ul li {
            float: left;
            display: block;
            width: 13%;
            margin-right: 1.5%;
        }
        
        #yearList a {
            float: left;
            display: block;
            font-size: 17px;
            width: 32%;
            margin: 7px;
            border-radius: 4px;
            margin-left: 0;
            margin-right: 2%;
            line-height: 50px;
            box-sizing: border-box;
            color: #333;
            background-color: #fafafa;
        }
        
        #yearList a:nth-child(3n) {
            margin-right: 0
        }
        
        #yearList {
            position: fixed;
            border-radius: 8px;
            box-shadow: 0 0 8px #ccc;
            top: 1%;
            left: 2%;
            bottom: 1%;
            right: 2%;
            z-index: 9;
            background-color: rgba(255, 255, 255, .95);
            overflow: scroll;
            display: none;
        }
        
        .cldrBody ul {
            margin: 12px 0;
        }
        
        .cldrBody span:last-child,
        .cldrBody ul li:nth-child(7n) {
            margin-right: 0
        }
        
        .cldrBody ul li {
            margin-bottom: 1.5%;
            height: 45px;
            line-height: 45px;
            background-color: #fafafa;
            color: #333;
            border-radius: 3px
        }
        
        .cldrBody ul li.preMounth {
            font-size: 12px;
            color: #999;
        }
        
        .cldrBody ul li.passed {
            color: #999;
        }
        
        .cldrBody ul li.innow {
            color: #fff;
            background-color: skyblue;
        }
        
        .arrs {
            display: block;
            position: relative;
            float: left;
            width: 30%;
            height: 70px;
        }
        
        .arrs::before {
            content: "";
            display: block;
            position: absolute;
            height: 16px;
            width: 16px;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%) rotateZ(45deg);
            /*background-color: skyblue;*/
            border: 1px solid slategray;
        }
        
        #ltArr.arrs::before {
            border-top: 0;
            border-right: 0
        }
        
        #rtArr.arrs::before {
            border-bottom: 0;
            border-left: 0
        }
        
        .lunaName {
            float: left;
            width: 40%;
        }

类似如此的选择器 :nth-child(7n)代表 逢7的倍数时,附上对应的样式。

JS 结构
        var odate = document.getElementById('datesWrp');
        var nowDate = new Date(); //获取当前日期
        var nowdate = nowDate.getDate(); //当前日期的几号
        var nowmonth = nowDate.getMonth(); //当前日期的月份
        var nowyear = nowDate.getFullYear(); //当前日期的年份
        var yearMonthDayRun = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; //闰年每个月的总天数
        var yearMonthDay = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; //平年每个月的总天数
        var englishNameOfMonth = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
        var chineseNameOfMonth = ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"];


        //如果是闰年则返回true
        function runNian(yearNum) {
            if (yearNum % 4 == 0 && yearNum % 100 != 0 || yearNum % 400 == 0) {
                return true;
            } else {
                return false;
            }
        }


        //这里让每个月的日期生成,传入年份,月份
        function outPutli(yearStr, monthStr) {
            var str = "";
            var yearNum = Number(yearStr); //转成数字类型
            var monthNum = Number(monthStr) - 1; //js的月份从0开始,也就是0代表一月,1代表二月
            var firstDayDate = new Date(yearNum, monthNum, 1).getDay(); //获取月份第一天礼拜几

            var previousMonth = monthNum - 1; //上个月的月份

            // 上个月的天数计算
            var previousdayCount = runNian(yearNum) ? yearMonthDayRun[previousMonth] : yearMonthDay[previousMonth];

            //传入月份的天数计算
            var theDayCount = runNian(yearNum) ? yearMonthDayRun[monthNum] : yearMonthDay[monthNum];

            //如果当前月是一月,那上个月就是上一年的12月
            if (monthNum == 0) {
                var previousMonth = 11;
                var previousdayCount = runNian(yearNum - 1) ? yearMonthDayRun[previousMonth] : yearMonthDay[previousMonth];
            }

            //算出传入月份的第一天礼拜几,就知道上个月的末尾有几天是在1号前面
            for (var i = previousdayCount - firstDayDate + 1; i <= previousdayCount; i++) {
                str += "<li class='preMounth'>" + i + "</li>";
            }

            //生产传入月份的各个天数
            for (var i = 1; i <= theDayCount; i++) {
                // 如果等于现在的日期,给个蓝色底
                if (yearNum == nowyear && monthNum == nowmonth && i == nowdate) {
                    str += "<li class='innow'>" + i + "</li>";
                }
                // 如果都是已经过去的日期,就淡化文字颜色
                else if (yearNum < nowyear || yearNum == nowyear && monthNum < nowmonth || yearNum == nowyear && monthNum == nowmonth && i < nowdate) {
                    str += "<li class='passed'>" + i + "</li>";
                } else {
                    str += "<li>" + i + "</li>";
                }
            }
            odate.innerHTML = str;
        }

        outPutli(nowyear, nowmonth + 1)

        var oYearBtn = document.getElementById('yearWrp');
        var oYearList = document.getElementById('yearList');
        var aBtnYear = oYearList.getElementsByTagName('a');

        //年份按钮点击的时候生成相对于现在,前16年和后36年的年份
        oYearBtn.onclick = function() {
            var yearNumber = Number(nowyear);
            var strs = "";

            for (var i = 16; i >= 0; i--) {
                // 因为a是代码生成的,所以绑定的事件要一并写上才有效果
                strs += "<a href='javascript:;' onclick='yearSelect(this)'>" + (yearNumber - i) + "</a>";
            }
            for (var i = 1; i <= 36; i++) {
                strs += "<a href='javascript:;' onclick='yearSelect(this)'>" + (yearNumber + i) + "</a>";
            }
            oYearList.innerHTML = strs;
            oYearList.style.display = "block";
        }

        // 年份选择后的操作,月份默认为当年一月
        function yearSelect(_this) {
            oYearBtn.innerHTML = _this.innerHTML;
            oYearList.style.display = 'none';
            outPutli(_this.innerHTML, 1);
            olunaName.setAttribute('data-mouthNum', 1);
            olunaName.getElementsByTagName('h2')[0].innerText = chineseNameOfMonth[0];
            olunaName.getElementsByTagName('h3')[0].innerText = englishNameOfMonth[0];
        }

        var oltArr = document.getElementById('ltArr');
        var ortArr = document.getElementById('rtArr');
        var olunaName = document.getElementsByClassName('lunaName')[0];

        // 改变月份的显示
        function changeTheMonthName(numberMonth) {
            olunaName.setAttribute('data-mouthNum', numberMonth);
            olunaName.getElementsByTagName('h2')[0].innerText = chineseNameOfMonth[numberMonth - 1];
            olunaName.getElementsByTagName('h3')[0].innerText = englishNameOfMonth[numberMonth - 1];
        }

        //左箭头点击时效果,月份减
        oltArr.onclick = function() {
            var numberMonth = olunaName.getAttribute('data-mouthNum');
            if (numberMonth > 1) {
                numberMonth--;
            }
            outPutli(oYearBtn.innerHTML, numberMonth);
            changeTheMonthName(numberMonth);
        }

        //右箭头点击时效果,月份加
        ortArr.onclick = function() {
            var numberMonth = olunaName.getAttribute('data-mouthNum');
            if (numberMonth < 12) {
                numberMonth++;
            }
            outPutli(oYearBtn.innerHTML, numberMonth);
            changeTheMonthName(numberMonth);
        }

算是加了比较详细的备注,小伙伴有兴趣的,可以慢慢研究下。若有不足,还请多多指教!

好了,到此,本文告一段落!感谢您的阅读!祝你身体健康,阖家幸福!

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

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,727评论 1 92
  • 一:在制作一个Web应用或Web站点的过程中,你是如何考虑他的UI、安全性、高性能、SEO、可维护性以及技术因素的...
    Arno_z阅读 1,136评论 0 1
  • <a name='html'>HTML</a> Doctype作用?标准模式与兼容模式各有什么区别? (1)、<...
    clark124阅读 3,455评论 1 19
  • 使用纯 CSS 实现 500px 照片列表布局 文章很长,因为介绍了如何一步一步进化到最后接近完美的效果的,不想读...
    HZ充电大喵阅读 2,610评论 0 4
  • 运动和健身是一回事吗? 运动:一种涉及体力和技巧的由一套规则或习惯所约束的活动,通常具有竞争性。 健身是一种体育项...
    伪思考宰飞阅读 849评论 0 5