共计 5200 个字符,预计需要花费 13 分钟才能阅读完成。
微信小程序简略日历实现(公历)
周六加班的时候,忽然想看看日历是怎么实现的,就试着写了一下。
————————– 分割线 ————————–
JS 局部
// pages/calendar/calendar.js | |
Page({ | |
/** | |
* 页面的初始数据 | |
*/ | |
data: {week: ["一", "二", "三", "四", "五", "六", "日"],// 星期 | |
maxDayList: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],// 一年 12 个月,每个月的天数,初始化都给平年 | |
nowYear: new Date().getFullYear(),// 以后年份 | |
nowMonth: new Date().getMonth()+1,// 以后月份 | |
totalDay: [],// 日历天数}, | |
/** | |
* 切换年、月 | |
*/ | |
changeDate(e) { | |
let type = e.currentTarget.dataset.type; | |
let nowYear = this.data.nowYear; | |
let nowMonth = this.data.nowMonth; | |
switch(type) { | |
case "preYear": // 上一年 | |
nowYear -= 1; | |
this.setData({nowYear}); | |
break; | |
case "preMonth": // 上一月 | |
nowMonth -= 1; | |
if(nowMonth <= 0) { | |
nowMonth = 12; | |
nowYear -= 1; | |
} | |
break; | |
case "nextMonth": // 下一月 | |
nowMonth += 1; | |
if(nowMonth >= 13) { | |
nowMonth = 1; | |
nowYear += 1; | |
} | |
break; | |
case "nextYear": // 下一年 | |
nowYear += 1; | |
break; | |
} | |
this.setData({nowYear, nowMonth}); | |
this.initCalendar();}, | |
/** | |
* 初始化日历 | |
*/ | |
initCalendar() { | |
let maxDayList = this.data.maxDayList; | |
let year = this.data.nowYear, month = this.data.nowMonth; | |
if((year%4 == 0 && year%100 != 0) || year%400 == 0) {// 计算以后年是不是平年,规定:能被 4 整除且不被 100 整除,或者能被 400 整除的年份 | |
maxDayList[1] = 29;// 2 月份 29 天 | |
} | |
let firstDayWeek = new Date(year + "-" + month + "-1").getDay() ;// 以后月的 1 号是星期几 | |
firstDayWeek = firstDayWeek > 0 ? firstDayWeek : 7;// 星期日从 0 转成 7 | |
let endDayWeek = new Date(year + "-" + month + "-" +maxDayList[month - 1]).getDay();// 以后月最初一天是星期几 | |
endDayWeek = endDayWeek > 0 ? endDayWeek : 7;// 星期日从 0 转成 7 | |
let beforArr = [], afterArr = [];//beforArr:本月 1 号之前须要补充上个月月尾几天,afterArr:本月尾补充下个月月初几天 | |
// 求出补充的上个月的日子 | |
for(let i=0; i<firstDayWeek-1; i++) {// 找出 1 号之前的空缺上个月的尾数日, 比方明天是周三,则 i =3-1, 取前两天的日子 | |
let deffTime = (i+1)*24*60*60*1000; // 缺的天数的毫秒值 | |
let firstTime = new Date(year + "-" + month + "-1").getTime();// 本月 1 号的毫秒值 | |
beforArr[i] = {otherMonth: true, day: new Date(firstTime - deffTime).getDate()};// 从对应月份的尾数天开始存,比方 31,30,29... | |
} | |
beforArr = beforArr.reverse();// 将补的上月的日子翻转 | |
// 求出补充的下个月的日子 | |
for(let i=0; i<7-endDayWeek; i++) {// 找出月尾对应的星期几,看看到周日还差几天就从下个月月初补几天 | |
afterArr[i] = {otherMonth: true, day: i+1}; | |
} | |
let nowMonthArr = [];// 以后月所有日子 | |
for(let i=0; i<maxDayList[month - 1]; i++) {nowMonthArr[i] = {day: i+1}; | |
if(year == new Date().getFullYear()) {// 如果切换到了本年本月本日,则凸显今日 | |
if(month == new Date().getMonth() + 1) {if(new Date().getDate() == i+1) {nowMonthArr[i].today = true; | |
} | |
} | |
} | |
} | |
let totalDayList = beforArr.concat(nowMonthArr).concat(afterArr);// 将所有日期拼接 | |
let totalDay = [], arr = [];//totalDay: 最终用来展现数据,arr:用来宰割每一周的日子 | |
for(let i=0; i<totalDayList.length; i++) {arr.push(totalDayList[i]); | |
if((i+1)%7 == 0) {// 每 7 天存为一组 | |
totalDay.push(arr); | |
arr = [];// 存完清空} | |
} | |
this.setData({totalDay}); | |
}, | |
/** | |
* 生命周期函数 -- 监听页面加载 | |
*/ | |
onLoad: function (options) { }, | |
/** | |
* 生命周期函数 -- 监听页面首次渲染实现 | |
*/ | |
onReady: function () {}, | |
/** | |
* 生命周期函数 -- 监听页面显示 | |
*/ | |
onShow: function () {this.initCalendar(); | |
}, | |
/** | |
* 生命周期函数 -- 监听页面暗藏 | |
*/ | |
onHide: function () {}, | |
/** | |
* 生命周期函数 -- 监听页面卸载 | |
*/ | |
onUnload: function () {}, | |
/** | |
* 页面相干事件处理函数 -- 监听用户下拉动作 | |
*/ | |
onPullDownRefresh: function () {}, | |
/** | |
* 页面上拉触底事件的处理函数 | |
*/ | |
onReachBottom: function () {}, | |
/** | |
* 用户点击右上角分享 | |
*/ | |
onShareAppMessage: function () {} | |
}) |
————————– 分割线 ————————–
wxml 局部
几个 image 按钮按程序是上一年、上个月、下个月、下一年,找不图片的能够用文字代替
<!--pages/calendar/calendar.wxml--> | |
<view class="calendar-page"> | |
<view class="calendar"> | |
<view class="btn-row"> | |
<image src="../../image/mine/calendar/arrow-left2.png" bindtap="changeDate" data-type="preYear"></image> | |
<image src="../../image/mine/calendar/arrow-left.png" bindtap="changeDate" data-type="preMonth"></image> | |
<view>{{nowYear + "-" + (nowMonth >= 10 ? nowMonth : "0" + nowMonth)}}</view> | |
<image src="../../image/mine/calendar/arrow-right.png" bindtap="changeDate" data-type="nextMonth"></image> | |
<image src="../../image/mine/calendar/arrow-right2.png" bindtap="changeDate" data-type="nextYear"></image> | |
</view> | |
<view class="week-row"> | |
<view class="week-item" wx:for="{{week}}" wx:key="index">{{item}}</view> | |
</view> | |
<view class="day-row" wx:for="{{totalDay}}" wx:for-item="item" wx:for-index="index" wx:key="index"> | |
<view wx:for="{{item}}" wx:for-item="subItem" wx:for-index="subIndex" wx:key="subIndex" | |
class="day-item {{subItem.today?'day-today':''}}{{subItem.otherMonth?'day-otherMonth':''}}" > | |
<text>{{subItem.day}}</text> | |
</view> | |
</view> | |
</view> | |
</view> |
————————– 分割线 ————————–
css 局部
/* pages/calendar/calendar.wxss */ | |
page { | |
height: 100%; | |
width: 100%; | |
background: #f3f5f9; | |
} | |
.calendar-page { | |
width: 100%; | |
height: 100%; | |
padding: 30rpx; | |
box-sizing: border-box; | |
} | |
.calendar { | |
border-radius: 30rpx; | |
background: #fff; | |
box-shadow:0rpx 24rpx 38rpx rgba(60, 128, 209, 0.09); | |
box-sizing: border-box; | |
padding: 30rpx; | |
} | |
.btn-row { | |
height: 70rpx; | |
line-height: 70rpx; | |
text-align: center; | |
font-size: 24rpx; | |
margin-bottom: 20rpx; | |
} | |
.btn-row view { | |
display: inline-block; | |
vertical-align: middle; | |
margin-right: 30rpx; | |
margin-left: 15rpx; | |
} | |
.btn-row image { | |
vertical-align: middle; | |
margin-right: 15rpx; | |
width: 25rpx; | |
height: 25rpx; | |
padding: 5rpx 10rpx; | |
border-radius: 10rpx; | |
border: 1rpx solid #00a8ff; | |
} | |
.week-row { | |
width: 100%; | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
} | |
.week-item { | |
width: 50rpx; | |
height: 50rpx; | |
text-align: center; | |
line-height: 50rpx; | |
font-size: 24rpx; | |
font-weight: bold; | |
color: #000000; | |
} | |
.day-row { | |
width: 100%; | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
margin-top: 20rpx; | |
} | |
.day-item { | |
width: 50rpx; | |
height: 50rpx; | |
text-align: center; | |
line-height: 50rpx; | |
font-size: 24rpx; | |
font-weight: bold; | |
color: #000000; | |
border-radius: 50%; | |
box-sizing: border-box; | |
} | |
.day-today { | |
background: #00a8ff; | |
color: #fff; | |
} | |
.day-otherMonth {color: #cdcdcd;} |
————————– 分割线 ————————–
阐明:只给今日加了蓝色背景,日历点击事件或者加备忘什么的没写,只写了根本款式,要写重要日子或者备忘之类的标记,可依据后盾返回数据给对应那天加上备忘标记,再写个小红点的款式即可。(临时看起来没什么问题,如有大佬发现问题,烦请回复,谢谢)
效果图:
正文完
发表至: javascript
2021-12-20