原生web实现

效果图

日历


Html

<div class="box">
	<div class="week">
		<div>星期日</div>
		<div>星期一</div>
		<div>星期二</div>
		<div>星期三</div>
		<div>星期四</div>
		<div>星期五</div>
		<div>星期六</div>
	</div>

	<div class="calendar_box">
		<div id="idBox" class="calendar"></div>
	</div>
	
	<div class="y_m_box">
		<div id="idShow" class="show_box"></div>
		<div id="idMBtn" class="m_btn_box"></div>
		<div id="idYBtn" class="y_btn_box"></div>
	</div>
</div>

JavaScript

代码

// 定义全局变量
let y = undefined,
    m = undefined,
    d = undefined;

// 创建日期
function creationDate(y, m, d) {
    let arr = [];

    for (let i = 1; i < d + 1; i++) arr.push(calendar.solar2lunar(y, m, i));

    return arr;
}

// 收集创建日期需要的数据(重要函数)
function createCalendar(y, m) {
    let y1 = y,
        y2 = y,
        y3 = y,
        m1 = m - 1,
        m2 = m,
        m3 = m + 1,
        d1 = 0,
        d2 = 0,
        d3 = 0,
        moth = [1, 3, 5, 7, 8, 10, 12],
        days = () => y % 2 === 0 ? 29 : 28,
        dayss = (val) => moth.includes(val) ? 31 : 30;

    if (m === 1) (y1 = y - 1, m1 = 12);
    if (m === 12) (y3 = y + 1, m3 = 1);

    d1 = m1 === 2 ? days() : dayss(m1);
    d2 = m2 === 2 ? days() : dayss(m2);
    d3 = m3 === 2 ? days() : dayss(m3);

    let arr1 = creationDate(y1, m1, d1),
        arr2 = creationDate(y2, m2, d2),
        arr3 = creationDate(y3, m3, d3),
        len2 = arr2.length,
        nWeek1 = arr2[0].nWeek,
        nWeek3 = arr2[len2 - 1].nWeek;

    nWeek1 = nWeek1 === 7 ? 0 : arr2[0].nWeek;
    nWeek3 = nWeek3 === 6 ? 0 : nWeek3 === 7 ? nWeek3 - 1 : 6 - nWeek3;

    for (let i = arr1.length - 1; nWeek1 > 0; i--) {
        let item = arr1[i];

        item.$b = 'different';
        arr2.unshift(item);
        nWeek1--;
    }

    for (let i = 0; i < nWeek3; i++) {
        let item = arr3[i];

        item.$b = 'different';
        arr2.push(item);
    }

    arr2 = arr2.map(item => {
        item.$SF = item.IDayCn === '初一' && !item.festival ? item.IMonthCn : item.festival ? item.festival : item.> IDayCn;

        return item;
    });

    return arr2;
}

// 页面渲染
function pageRendering(arr) {
    let str = '';

    for (let i = 0; i < arr.length; i++) {
        let item = arr[i];

        str += `<div class="item" style="background-color: ${item.$b ? 'rgba(0, 0, 0, .1)' : ''}; color: ${item.cDay > === d && item.cMonth === m ? '#FFA500' : ''};">
            <div class="south">${item.cDay}</div>
            <div class="lunar" style="color: ${item.festival ? '#0000ff' : ''}">${item.$SF}</div>
        </div>`;
    }

    idBox.innerHTML = str;
}

// 初始化
function init() {
    let date = new Date();

    y = date.getFullYear();
    m = date.getMonth() + 1;
    d = date.getDate();

    let arr = createCalendar(y, m);
    pageRendering(arr);

    let idYBtnStr = '',
        idMBtnStr = '';

    for (let i = 1990; i < 2030; i++) idYBtnStr += `<div class="y_item">${i}</div>`;
    for (let i = 0; i < 12; i++) idMBtnStr += `<div class="m_item">${i + 1}</div>`;

    idYBtn.innerHTML = idYBtnStr;
    idMBtn.innerHTML = idMBtnStr;
    assignment('m_item');
}

// 执行初始化
init();

// 选择年份
idYBtn.onclick = ({ target: { textContent, className } }) => {
    y = Number(textContent);

    assignment(className);
}

// 选择月份
idMBtn.onclick = function ({ target: { textContent, className } }) {
    m = Number(textContent);

    assignment(className);
}

// 年份/月份赋值
function assignment(className) {
    if (className === 'm_item' || className === 'y_item') {
        idShow.innerHTML = `<span>${y}</span> <span>${m}</span> <span>${d}</span>`;

        let arr = createCalendar(y, m);

        pageRendering(arr);
    }
}

npm插件下载指令
指令

npm install js-calendar-converter --save

cnpm install js-calendar-converter --S

yarn add js-calendar-converter

注释
1、在全局定义变量y、变量m和变量d3个变量分别用来存储当前选中的年份、月份和日期,初始值为undefined
2、定义名为createCalendar函数,createCalendar函数是本例最重要的函数。在createCalendar函数中会创建当前月的上月和下月所有日期数据,并且会组合成日历的形式返回准确数据,也就是把数据组成7天的形式返回。本月前部分不够那就用上月末的日期数据补上,后半部分不够就用下月初的日期数据补上,总之会组成3542个长度的数组数据。
第一步
定义3个保存年份值的变量,为什么要定义三个呢?有可能你会想,那年份不都一样吗!可惜年份不一定一样。当传入的月份是1时,年份就要倒退1年,并且取上一年的12月份做值;当传入月份是12时,年份就要加1,也就是来年的1月份值。
第二步
月份也需要定义3个变量保存值,当传入的值为7时,第1个变量保存6,第2个变量保存7,第3个变量保存8
第三步
同时日期也定义3个变量,不过这3个变量不是存储真正的日期值,而是存储当前月的最大日期值,比如当前月有28天,那就存28,如果是30天,那就存30,共有四种情况,分别是28293031,这些数据用来创建当月的完整日期值。
第四步
定义moth月份数组,数组中存放112月,每个月都是31天的月份序号。
第五步
定义days箭头函数判定2月份,因为2月有平年与闰年之分,需要通过特定的手段处理。
第六步
定义dayss箭头函数判定30天和31天的月份,结合第四步的moth数组来判定。
第七步
处理当前月为112时的年份值和上月值或下月值。
第八步
根据月份获取当月最大天数,首先判断是否是2月。
第九步
到上面的第八步时,相邻3个月的年份、月份和月份最大天数都已经准备好,接下来便是获取对应月份的所有天数值了。
定义名为creationDate的函数用来创建当月天数。函数参数分别是ymdy表示年份,m表示月份,d表示循环结束条件。这一步需要npm插件辅助,这个插件可以实现阳历和农历之间的相互转换。
第十步
经过第九步之后,我们便拿到了相邻3个月的所有日期值,里面包括阳历、农历和星期等相关值,把3个月的日期值分别存到3个变量中待用。
第十一步
处理星期显示的数据,掐头去尾。定义len2保存当前月的日期长度,获取当前月的日期数组第一项和最后一项星期值,并保存到两个变量中。
第十二步
nWeek1 === 7 ? 0 : arr2[0].nWeek当星期等于7时不需要从上个月获取数据补充,否则需要获取上个月对应的数据补齐一个星期,即需要让数据从星期日开始补齐,当星期值为7时说明当前月的1号正好是星期日。
nWeek3 === 6 ? 0 : nWeek3 === 7 ? nWeek3 - 1 : 6 - nWeek3当前月结束时需要补齐的数据值,如果当前月最后1天正好是星期六,那么不需要截取下个月的数据补齐一个星期;如果当前月最后一天是星期日,那么需要从下个月取6天来补全当前月数据;如果是其他星期值,那么就需要使用6减去当前星期值。这一步可能会有点晦涩难懂,希望我的注解能帮到你。
第十三步
第十二步拿到掐头去尾的准确值,那么开始实现掐头去尾的工作吧!掐头会比较麻烦一点,因为需要从数组的末尾开始截取数据,所以i的初始值是数组长度减1,并且i做减减操作,退出循环条件是第十二步中获取的nWeek1值,循环退出条件是nWeek1---1,但不包括-1,使用unshift向数组前面添加数据。去尾简单一点,直接循环加加就好,退出循环的条件是i < nWeek3,这里使用push向数组末尾添加数据。填充头部和尾部数据时给数据新增了一个属性$b用来判别当前月或上月下月的数据,以此来给日期数据显示不同的颜色。
最后一步
循环拼接组合好的数据设置农历月份和对应节日值。至此日历数据模板已创建完成,把最终数据返回即可。
3、关于其他函数不做解析,基本都是渲染相关操作啦!
4、html不做解释,自行阅读即可。
5、style不做解释,自行阅读即可。


Style

body {
	width: 100vw;
	height: 100vh;
	display: flex;
	justify-content: center;
	align-items: center;
	margin: 0;
}

.box {
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
}

.item {
	background-color: rgba(0, 0, 0, .3);
	padding: 2px 0;
	border-radius: 3px;
	cursor: pointer;
}

.south {
	font-size: 18px;
	font-weight: 700;
}

.lunar {
	font-size: 16px;
}

.week {
	display: grid;
	grid-template-columns: 86px 86px 86px 86px 86px 86px 86px;
	text-align: center;
	grid-column-gap: 10px;
	font-weight: 800;
	font-size: 20px;
}

.calendar_box {
	margin-top: 6px;
}

.calendar {
	display: grid;
	grid-template-columns: 86px 86px 86px 86px 86px 86px 86px;
	text-align: center;
	grid-row-gap: 10px;
	grid-column-gap: 10px;
}

.y_m_box {
	display: flex;
	flex-direction: column;
	align-items: center;
}

.y_btn_box {
	display: grid;
	grid-template-columns: 68px 68px 68px 68px 68px 68px 68px 68px;
	grid-column-gap: 20px;
	grid-row-gap: 20px;
}

.m_btn_box {
	width: 600px;
	margin: 10px 0;
	display: flex;
	justify-content: space-between;
}

.y_item,
.m_item {
	text-align: center;
	cursor: pointer;
	font-weight: 700;
	border-radius: 4px;
	padding: 2px 0;
	box-sizing: border-box;
	border: 1px solid rgba(0, 0, 0, .1);
	box-shadow: 0px 1px rgba(0, 0, 0, .3);
}

.y_item {
	font-size: 16px;
}

.m_item {
	width: 36px;
	font-size: 18px;
}

.show_box {
	margin-top: 10px;
	font-size: 30px;
	font-weight: 900;
	color: #FFA500;
}

vue2实现

Html

敬请期待… …


JavaScript

敬请期待… …


js-calendar-converter插件的详细介绍

web前端之js-calendar-converter日历插件的使用、日期、转换、阳历、阴历、公历、农历、calendar

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐