mini日历实现

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <link href="./index.css" rel="stylesheet" type="text/css"></link>
    <script src="./index.js" async></script>
</head>
<body>
    <div class="calendar">
     <div class="years-group" id="years-group">
     <span class="years-item prev-year" id="prev-year"></span>
     <span class="years-item current-year"></span>
     <span class="years-item next-year" id="next-year"></span>
     </div>
     <div class="month-switcher">
     <span class="month-item prev-month" id="prev-month"></span>
     <span class="month-item current-month" id="current-month"></span>
     <span class="month-item next-month" id="next-month"></span></span>
     </div>
     <div class="week-holder">
     <span class="week-day">日</span>
     <span class="week-day">一</span>
     <span class="week-day">二</span>
     <span class="week-day">三</span>
     <span class="week-day">四</span>
     <span class="week-day">五</span>
     <span class="week-day">六</span>
     </div>
     <div class="date-list" id="date-list"></div>
    </div>
</body>
</html>
 
css
 
/* ------ Reset ------------------------------------------------------- */
* {
padding: 0;
margin: 0;
}

/* ------ Document ---------------------------------------------------- */
html {
line-height: 1.15;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 16px;
color: #7081d6;
-webkit-font-smoothing: antialiased;
}

/* ------ Element ----------------------------------------------------- */
/* == ------ Calendar ------------------------------------------------- */
.calendar {
box-sizing: border-box;
width: 364px;
padding: 12px 14px 20px;
margin: 10px;
border-radius: 5px;
background-color: #0f1a56;
font-weight: bolder;
}

/* ==== ------ Years-Group -------------------------------------------- */
.years-group {
margin-top: 8px;
line-height: 40px;
text-align: center;
}

.years-item {
padding: 0 16px;
vertical-align: baseline;
}

.prev-year,
.next-year {
opacity: .8;
transition: opacity .15s ease-in;
}

.prev-year:hover,
.next-year:hover {
opacity: 1;
cursor: pointer;
}

.years-group .current-year {
font-size: 28px;
}

/* ==== ------ Month-Switcher ----------------------------------------- */
.month-switcher {
margin-bottom: 8px;
line-height: 44px;
text-align: center;
}

.month-item {
display: inline-block;
margin: 8px;
vertical-align: middle;
}

.prev-month,
.next-month {
width: 20px;
height: 20px;
border-radius: 4px;
background-repeat: no-repeat;
background-position: center center;
opacity: .65;
transition: opacity .2s ease-out;
}

.prev-month {
/* background-image: url('../../images/icons/arrow-left.png'); */
background: #1fcda5;
}

.next-month {
/* background-image: url('../../images/icons/arrow-right.png'); */
background: #1fcda5;
}

.prev-month:hover,
.next-month:hover {
background-color: rgba(112, 129, 214, .9);
opacity: .8;
cursor: pointer;
}

.current-month {
padding: 0 10px;
font-size: 18px;
}

/* ==== ------ Week-Holder ------------------------------------------- */
.week-holder {
display: flex;
line-height: 32px;
}

.week-day {
flex: 1;
color: #1fcda5;
text-align: center;
}

/* ==== ------ Date-List --------------------------------------------- */
.date-list {
display: flex;
flex-wrap: wrap;
}

.date-item {
width: 48px;
height: 48px;
line-height: 48px;
font-size: 0;
text-align: center;
}

.date-badge {
display: inline-block;
width: 32px;
height: 32px;
border-radius: 50%;
line-height: 32px;
font-size: 16px;
vertical-align: middle;
transition: all .1s ease-in;
}

.date-badge:hover {
background-color: rgba(27, 42, 116, .8);
cursor: pointer;
}

.date-list .current-date {
position: relative;
width: 28px;
height: 28px;
background-color: rgba(255, 59, 128, .82);
line-height: 28px;
color: rgba(255, 255, 255, .9);
}

.date-list .current-date::after {
content: '';
position: absolute;
top: -6px;
left: -6px;
width: 28px;
height: 28px;
border: 6px solid rgba(255, 57, 127, .35);
border-radius: 50%;
background-color: transparent;
}
 
js
 
/**
* 获取指定的DOM元素
* @param {string} selector
* @return {object} 单个元素或元素集合
*/
function $(selector) {
if (/^#/.test(selector)) {
return document.querySelector(selector);
}
return document.querySelectorAll(selector);
}
 
/**
* 将类数组转换为真实数组
* @param {NodeList} likeArray
* @return {array} 真实数组
*/
function toArray(likeArray) {
return Array.prototype.slice.call(likeArray);
}
 
/**
* 初始化日历
*/
function CalendarInit() {
const date = new Date();
const realYear = date.getFullYear();
const realMonth = date.getMonth() + 1;
const realDay = date.getDate();
const dateList = $('#date-list');
const currentMonthTextContainer = $('#current-month');

let currentYear = realYear; // 当前年份
let currentMonth = realMonth; // 当前月份
 
// 判断是否为闰年
const isLeapYear = (() => {
if (
currentMonth % 400 === 0
|| (currentMonth % 4 === 0 && currentMonth % 100 !== 0)
) {
return true;
}
 
return false;
})();
 
// 获取年份单元
const getYearsGroup = (yearNumber) => {
return [yearNumber - 1, yearNumber, yearNumber + 1];
};
 
// 展示年份单元
const renderYearsGroup = (yearsArray) => {
const yearNodeList = toArray($('.years-item'));
 
yearsArray.forEach((year, index) => {
yearNodeList[index].innerHTML = year;
});
};
 
// 切换到上一年
const toPrevYear = () => {
currentYear -= 1;
renderYearsGroup(getYearsGroup(currentYear));
};
 
// 切换到下一年
const toNextYear = () => {
currentYear += 1;
renderYearsGroup(getYearsGroup(currentYear));
};
 
// 获取转化后的汉字月份
const getMonthChineseText = (monthNumber) => {
switch (monthNumber) {
case 1:
return '一月';
case 2:
return '二月';
case 3:
return '三月';
case 4:
return '四月';
case 5:
return '五月';
case 6:
return '六月';
case 7:
return '七月';
case 8:
return '八月';
case 9:
return '九月';
case 10:
return '十月';
case 11:
return '十一月';
case 12:
return '十二月';
default:
return '';
}
};
 
// 渲染当前月份
const renderCurrentMonthText = (monthNumber) => {
currentMonthTextContainer.innerHTML = getMonthChineseText(monthNumber);
};
 
// 获取指定月份的天数
const getCurrentMonthDays = (monthNumber) => {
switch (monthNumber) {
case 1:
return 31;
case 2:
return isLeapYear ? 29 : 28;
case 3:
return 31;
case 4:
return 30;
case 5:
return 31;
case 6:
return 30;
case 7:
return 31;
case 8:
return 31;
case 9:
return 30;
case 10:
return 31;
case 11:
return 30;
case 12:
return 31;
default:
return 0;
}
};
 
// 获取某月的第一天是星期几
const getWeekDayNumberOnTheFirstDayOfCurrentMonth = () => {
const month = currentMonth > 9 ? currentMonth : ('0' + currentMonth);
const firstDay = `${currentYear}-${month}-01`;
 
return (new Date(firstDay)).getDay();
};
 
// 生成日历单元的html字符串
const generateItemHtmlString = (dayNumber, classDecorator = '') => {
if (classDecorator) {
classDecorator = ` ${classDecorator}`;
}
 
return `
<div class="date-item">
<span class="date-badge${classDecorator}">${dayNumber}</span>
</div>
`;
};
 
// 渲染日历
const renderCalendarItems = () => {
const currentMonthWholeDays = getCurrentMonthDays(currentMonth);
const startDay = getWeekDayNumberOnTheFirstDayOfCurrentMonth();
const currentDayClassName = 'current-date';
let templateString = '';
let dayMark = 0;
 
for (let i = 0; i < currentMonthWholeDays + startDay; i++) {
dayMark = i + 1 - startDay;
 
if (
currentYear === realYear
&& currentMonth === realMonth
&& dayMark === realDay
) {
templateString += generateItemHtmlString(dayMark, currentDayClassName);
continue;
}
 
if (i >= startDay) {
templateString += generateItemHtmlString(dayMark);
continue;
}
 
// 补空
templateString += '<div class="date-item"></div>';
}
 
dateList.innerHTML = templateString;
};
 
// 处理年份变化
const handleYearControllerChange = () => {
const prevYear = $('#prev-year');
const nextYear = $('#next-year');
 
prevYear.addEventListener('click', () => {
toPrevYear();
renderCalendarItems();
});
 
nextYear.addEventListener('click', () => {
toNextYear();
renderCalendarItems();
});
};
 
// 处理月份变化
const handleMonthControllerChange = () => {
const prevMonth = $('#prev-month');
const nextMonth = $('#next-month');
 
prevMonth.addEventListener('click', () => {
if (currentMonth === 1) {
toPrevYear();
currentMonth = 12;
} else {
currentMonth -= 1;
}
 
renderCurrentMonthText(currentMonth);
renderCalendarItems();
});
 
nextMonth.addEventListener('click', () => {
if (currentMonth === 12) {
toNextYear();
currentMonth = 1;
} else {
currentMonth += 1;
}
 
renderCurrentMonthText(currentMonth);
renderCalendarItems();
});
};
 
renderYearsGroup(getYearsGroup(currentYear));
renderCurrentMonthText(currentMonth);
renderCalendarItems();
handleYearControllerChange();
handleMonthControllerChange();
}
 
CalendarInit();

 

posted @ 2019-06-20 11:48  cwxwdm  阅读(283)  评论(0编辑  收藏  举报