小程序自定义日历效果
本文实例为大家分享了程序" title="小程序">小程序自定义日历展示的具体代码,供大家参考,具体内容如下
重点在于将数个月的日期拆分重组,然后再统一以月为输出。详细操作代码注释有说明。
<view class="flex box box-tb box-align-center">
<!--整体日期循环部分 -->
<block wx:for="{{allMan}}" wx:for-item="item" >
<view class="calendar pink-color box box-tb">
<view class="top-handle fs28 box box-lr box-align-center box-pack-center">
<view class="date-area box box-lr box-align-center box-pack-center years-month">{{item.year || "--"}} 年 {{item.Month || "--"}} 月</view>
</view>
<!--展示星期几的头部 -->
<view class="weeks box box-lr box-pack-center box-align-center day-week">
<view class="flex week fs28" wx:for="{{weeks_ch}}" wx:key="{{index}}" data-idx="{{index}}">{{item}}</view>
</view>
<view class="days box box-lr box-wrap">
<view class="grid white-color box box-align-center box-pack-center" wx:for="{{item.empyt}}" wx:key="{{index}}" data-idx="{{index}}">
</view>
<!--循环日期 -->
<block wx:for="{{item.day}}" wx:for-item="item" wx:key="{{index}}">
<view class="grid white-color box box-align-center box-pack-center" data-idx="{{index}}" data-dayz="{{item.dayZ}}" bindtap="{{item.canChoosed ? 'tapDayItemX' : ''}}">
<view class="day {{item.dependence ? 'border-instinct pink-bg' : ''}} {{item.startDay ? 'border-radius dependence-bg' : ''}} {{item.endDay ? 'border-right-radius dependence-bg' : ''}} {{item.canChoosed ? '' : 'grays'}} box box-align-center box-pack-center">
{{item.today}}
</view>
</view>
</block>
</view>
</view>
</block>
</view>
.js:
let choose_year = null,//选择的年
choose_month = null;//选择的月
let clickNum=new Array();//点击日期的次数,做显示判断处理
let date = new Date();
let cur_year = date.getFullYear();
let cur_month = date.getMonth() + 1;
let weeks_ch = ['日', '一', '二', '三', '四', '五', '六']; //日历的显示
let allMan = new Array();//循环总日历容器
let haveClickNum=false;//是否可点击选择日期
let havInitDate = false;//是否已经重置数据
let conf = {//拿去给Page
onLoad() {
if (allMan.length != 0) {//重新进入界面发现已经有数据,直接渲染
havInitDate = false;
clickNum = new Array();
haveClickNum = true;
this.setData({
allMan,
weeks_ch
})
}else{
allMan = new Array();//非常重要的主输出,计算好的每月数据都合拼在里面
clickNum = new Array();
let that = this;
let empytGrids = this.calculateEmptyGrids(cur_year, cur_month);//计算空格
let days = this.calculateDays(cur_year, cur_month);//计算日期总数
let DogDays = { year: cur_year, Month: cur_month, empyt: empytGrids, day: days };//组装年、月、星期一前的空格、日
allMan.push(DogDays);
let newMonth = cur_month + 1;
let newYear = cur_year;
if (newMonth > 12) {//新年重置1月份
newYear = cur_year + 1;
newMonth = 1;
}
let empytGridsTwos = this.calculateEmptyGridsTwo(newYear, newMonth);//计算新月份的空格
let dayTwos = this.calculateDaysTwo(newYear, newMonth);//计算日期总数
let catDays = { year: newYear, Month: newMonth, empyt: empytGridsTwos, day: dayTwos };
allMan.push(catDays);
let sakura = days.concat(dayTwos);//将存放日期的内容统一合并为数组,单独处理是否可选等展示状态,属于中间件数组
let isTrue = new Array();//存放可选
for (var i = 0; i < sakura.length; i++) {//循环处理
if (sakura[i].canChoosed == true) {
isTrue.push(sakura[i]);
} else {
continue
}
}
let addMoreMonth = function () {//添加更多的月份
let isTrue = new Array();//是否可选的日期数组,为N个月等可选日期总日输做判断
for (var i = 0; i < sakura.length; i++) {
if (sakura[i].canChoosed == true) {
isTrue.push(sakura[i]);
} else {
continue
}
}
let newMonthThree = newMonth + 1;
let newYearThree = newYear;
if (newMonthThree > 12) {
newYearThree = newYear + 1;
newMonthThree = 1;
}
let empytGridsThree = that.calculateEmptyGridsTwo(newYearThree, newMonthThree);//计算空格
let dayThree = that.calculateDaysTwo(newYearThree, newMonthThree, 91 - isTrue.length);//计算日期总数,61减,今天不算
let duckDays = { year: newYearThree, Month: newMonthThree, empyt: empytGridsThree, day: dayThree };
sakura = sakura.concat(dayThree);
allMan.push(duckDays);
if (parseInt(91 - isTrue.length) > parseInt(dayThree.length)) {//第n个月是否足够显示需要的可选日期长度
for (var i = 0; i < dayThree.length; i++) {
if (dayThree[i].canChoosed == true) {
isTrue.push(dayThree[i]);
} else {
continue
}
}
let newMonthFour = newMonthThree + 1;
let newYearFour = newYearThree;
if (newMonthFour > 12) {
newYearFour = newYearThree + 1;
newMonthFour = 1;
}
let empytGridsFour = that.calculateEmptyGridsTwo(newYearFour, newMonthFour);//计算空格
let dayFour = that.calculateDaysTwo(newYearFour, newMonthFour, 91 - isTrue.length);//计算日期总数,61减,今天不算
let wolfDays = { year: newYearFour, Month: newMonthFour, empyt: empytGridsFour, day: dayFour };
sakura = sakura.concat(dayFour);
allMan.push(wolfDays);
} else {//不足够继续增加第n+1个月
let newMonthFour = newMonthThree + 1;
let newYearFour = newYearThree;
if (newMonthFour > 12) {
newYearFour = newYearThree + 1;
newMonthFour = 1;
}
let empytGridsFour = that.calculateEmptyGridsTwo(newYearFour, newMonthFour);//计算空格
let dayFour = that.calculateDaysTwo(newYearFour, newMonthFour, -1);//计算日期总数,61减,今天不算
let wolfDays = { year: newYearFour, Month: newMonthFour, empyt: empytGridsFour, day: dayFour };
sakura = sakura.concat(dayFour);
allMan.push(wolfDays);
}
}
if (isTrue.length < 90) {
addMoreMonth();
}
this.setData({
allMan,
weeks_ch
})
}
},
onShow: function () {
// console.log(allMan);
// allMan = new Array();//循环总日历容器
// 页面显示
},
getThisMonthDays(year, month) {
return new Date(year, month, 0).getDate();
},
getFirstDayOfWeek(year, month) {
return new Date(Date.UTC(year, month - 1, 1)).getDay();
},
calculateEmptyGrids(year, month) {
let firstDayOfWeek = this.getFirstDayOfWeek(year, month);
let empytGrids = [];
if (firstDayOfWeek > 0) {
for (let i = 0; i < firstDayOfWeek; i++) {
empytGrids.push(i);
}
}
return (empytGrids);
},
calculateEmptyGridsTwo(year, month) {
let firstDayOfWeek = this.getFirstDayOfWeek(year, month);
let empytGridsTwo = [];
if (firstDayOfWeek > 0) {
for (let i = 0; i < firstDayOfWeek; i++) {
empytGridsTwo.push(i);
}
}
return (empytGridsTwo);
},
calculateDays(year, month) {
let days = [];
let date = new Date();
let thisMonthDays = this.getThisMonthDays(year, month);//这个月的总日数
let d = date.getDate();
let weeHours=date.getHours();
let zaa = year+month+date.getDate();
for (let i = 1; i <= thisMonthDays; i++) {
if (year+month+i == zaa){
days.push({
day: i,
dayZ: cur_year+"-"+cur_month+"-"+i,
choosed: false,
canChoosed: true,
today: i
});
} else if (year + month + i < zaa){
if (weeHours <= 2 && year + month + i == zaa-1){//加个判断:是否凌晨3点之前,是的话就拿日期集-1来对前一日可选
days.push({
day: i,
dayZ: cur_year + "-" + cur_month + "-" + i,
choosed: false,
canChoosed: true,
today: i
});
}else{
days.push({
day: i,
dayZ: cur_year + "-" + cur_month + "-" + i,
choosed: false,
canChoosed: false,
today: i
});
}
} else{
days.push({
day: i,
dayZ: cur_year + "-" + cur_month + "-" + i,
choosed: false,
canChoosed: true,
today: i
});
}
}
this.setData({
// days
});
return (days);
},
calculateDaysTwo(year, month,takeNum) {
let days_two = [];
let date = new Date();
let thisMonthDays = this.getThisMonthDays(year, month);
let d = date.getDate();
let zaa = year+"-"+month+"-"+date.getDate();
if (takeNum) {
console.log(takeNum);
}
for (let i = 1; i <= thisMonthDays; i++) {
takeNum--;
if (takeNum<0){
days_two.push({
day: i,
dayZ: year + "-" + month + "-" + i,
choosed: false,
canChoosed: false,
today: i
});
}else{
days_two.push({
day: i,
dayZ: year + "-" + month + "-" + i,
choosed: false,
canChoosed: true,
today: i
});
}
}
this.setData({
// days_two
});
return (days_two);
},
handleCalendar(e) {
let handle = e.currentTarget.dataset.handle;
let cur_year = this.data.cur_year;
let cur_month = this.data.cur_month;
if (handle === 'prev') {
let newMonth = cur_month - 1;
let newYear = cur_year;
if (newMonth < 1) {
newYear = cur_year - 1;
newMonth = 12;
}
this.calculateDays(newYear, newMonth);
this.calculateEmptyGrids(newYear, newMonth);
this.setData({
cur_year: newYear,
cur_month: newMonth
});
} else {
let newMonth = cur_month + 1;
let newYear = cur_year;
if (newMonth > 12) {
newYear = cur_year + 1;
newMonth = 1;
}
this.calculateDays(newYear, newMonth);
this.calculateEmptyGrids(newYear, newMonth);
this.setData({
cur_year: newYear,
cur_month: newMonth
});
}
},
tapDayItemX(e) {//点击日期处理
if (clickNum.length >= 2)//点了两次,不可再点
return;
if (haveClickNum){//是否已经选择过日期
this.initChosedDate();//重置选择过的样式
let dayZ = e.currentTarget.dataset.dayz;
for (let i = 0; i < allMan.length; i++) {
let li = allMan[i].day;
for (let k = 0; k < li.length; k++) {
if (li[k].dayZ == dayZ) {
if (clickNum.length == 0) {
li[k].startDay = true;
}
if (clickNum.length == 1) {
li[k].endDay = true;
}
}else{//已选择的区间日期重置
li[k].dependence = false;
}
}
}
this.setData({//渲染
allMan
})
clickNum.push(integerDate(dayZ));//格式化日期,准备拿去比较函数处理
}else{//第一次进入生命周期,从没选择过的处理
let dayZ = e.currentTarget.dataset.dayz;
for (let i = 0; i < allMan.length; i++) {
let li = allMan[i].day;
for (let k = 0; k < li.length; k++) {
if (li[k].dayZ == dayZ) {
if (clickNum.length == 0) {
li[k].startDay = true;
}
if (clickNum.length == 1) {
li[k].endDay = true;
}
}
}
}
this.setData({//渲染
allMan
})
clickNum.push(integerDate(dayZ));//格式化日期,准备拿去比较函数处理
}
if (clickNum.length < 2)//点击了第二次,进行teturn下面的渲染操作
return
clickNum.sort(compare);//拿去比较函数处理
let dayDiff = GetDateDiff(clickNum[0], clickNum[1]);
let startDay = clickNum[0];//第一位为开始日期
let startMonth = new Date(clickNum[0]).getMonth() + 1;//开始的月,跨月显示用
let formatStartDay = new Date(clickNum[0]).getFullYear() + '-' + startMonth + '-' + new Date(clickNum[0]).getDate();//格式化开始日期,后面用于给总输出allman做判断
let endMonth = new Date(clickNum[1]).getMonth() + 1;//结束的月,跨月显示用
let formatEndDay = new Date(clickNum[1]).getFullYear() + '-' + endMonth + '-' + new Date(clickNum[1]).getDate();//格式化结束日期,后面用于给总输出allman做判断
let endDay = clickNum[1];//第二位为结束日期
for (let i = 0; i < allMan.length; i++) {//循环总输出allMan数组得出每月的日期数组,将开始、结束日期带进去做改变显示状态处理
let li = allMan[i].day;
for (let k = 0; k < li.length; k++) {//每个月的日期数组,拆分更细
let foxDay = integerDate(li[k].dayZ);
if (startDay < foxDay && foxDay < endDay){
li[k].dependence = true;//已选择的区间日期
} else if (li[k].dayZ == formatStartDay){//开始日期状态处理
li[k].startDay = true;
li[k].endDay = false;
} else if (li[k].dayZ == formatEndDay) {//结束日期状态处理
li[k].startDay = false;
li[k].endDay = true;
}
}
}
this.setData({//再渲染
allMan
})
wx.navigateBack({
delta: 1,
})
},
initChosedDate(){
if (havInitDate)
return
for (let i = 0; i < allMan.length; i++) {
let li = allMan[i].day;
for (let k = 0; k < li.length; k++) {
li[k].startDay = false;
li[k].endDay = false;
}
}
havInitDate=true;
},
};
Page(conf);
let compare = function (x, y) {//比较函数,那个日期谁先谁后,star/end
if (x < y) {
return -1;
} else if (x > y) {
return 1;
} else {
return 0;
}
}
function GetDateDiff(startDate, endDate) {
let dates = Math.abs((startDate - endDate)) / (1000 * 60 * 60 * 24);
return dates;
}
function integerDate(choseDate){
let integerDay = new Date(Date.parse(choseDate.replace(/-/g, "/"))).getTime();
return integerDay;
}
.wxss:
/* pages/calendar/calendar.wxss */
.top-handle {
height: 80rpx;
}
.prev {
text-align: right;
height: 80rpx;
}
.next {
height: 80rpx;
}
.prev-handle {
width: 80rpx;
height: 100%;
}
.next-handle {
width: 80rpx;
height: 100%;
}
.date-area {
width: 50%;
height: 80rpx;
text-align: center;
}
.weeks {
height: 50rpx;
line-height: 50rpx;
opacity: 0.5
}
.week {
text-align: center;
}
.days {
height: 500rpx;
}
.grid {
width: 107.1428571429rpx;
}
.day {
width: 100%;
height: 100%;
color: #000;
font-size: 26rpx;
font-weight: 200;
}
.border-instinct{
position: relative;
left: 0;
top: 0;
color: #fff;
}
.border-radius {
border-radius:5px 0 0 5px;
position: relative;
left: 0;
top: 0;
color: #fff;
}
.border-right-radius {
border-radius:0 5px 5px 0;
position: relative;
left: 0;
top: 0;
color: #fff;
}
.pink-bg {
background-color: #ffe5b4;
color: #f6ac1d;
}
.dependence-bg {
background-color: #d9246b;
}
.purple-bg {
background-color: #b8b8f1;
}
.right-triangle::after {
content: "";
display: block;
width: 0;
height: 0;
border: 15rpx solid transparent;
border-left-color: #ff629a;
position: absolute;
right: -22rpx;
top: 18rpx;
}
.left-triangle::before {
content: "";
display: block;
width: 0;
height: 0;
border: 15rpx solid transparent;
border-right-color: #ff629a;
position: absolute;
left: -22rpx;
top: 18rpx;
}
.tips {
text-align: center;
margin-top: 20rpx;
margin-bottom: 20rpx;
}
.types {
background-color: #ffedf4;
height: 50rpx;
}
.type-dot {
width: 25rpx;
height: 25rpx;
border-radius: 50%;
margin-right: 10rpx;
}
.type-dot-ymq {
color:#FF7CA0;
background-color: #FF7CA0;
}
.type-dot-ycq {
color: rgb(255, 200, 202);
background-color: rgb(255, 200, 202);
}
.type-dot-aqq {
color: rgb(118, 191, 92);
background-color: rgb(118, 191, 92);
}
.type-dot-yyq {
color: #FF7CA0;
background-color: #FF7CA0;
}
.type-dot-plr {
color: rgb(211, 189, 215);
background-color: rgb(211, 189, 215);
}
.types-desc {
padding: 0 20rpx;
}
.type-name {
margin-top: 50rpx;
margin-bottom: 30rpx;
}
.type-desc {
padding: 0 35rpx;
line-height: 38rpx;
}
.explain {
border-top: 1px solid #eee;
width: 90%;
margin: 20rpx 5% 20rpx 5%;
padding: 20rpx 0;
}
.explain-title {
font-weight: bold;
margin-bottom: 15rpx;
}
.explain-item {
padding: 8rpx 20rpx;
color: #fff;
}
.left-border-radius {
border-top-left-radius: 20rpx;
border-bottom-left-radius: 20rpx;
}
.right-border-radius {
border-top-right-radius: 20rpx;
border-bottom-right-radius: 20rpx;
}
.picker-btns {
height: 120rpx;
line-height: 120rpx;
border-bottom: 1rpx solid #FF7CA0;
}
.picker-confirm {
margin-right: 50rpx;
}
.picker-cancel {
margin-left: 50rpx;
}
.picker-view {
color:#FF7CA0;
text-align: center;
}
.box {
display: flex;
}
.box-lr {
flex-direction: row;
}
.box-rl {
flex-direction: row-reverse;
}
.box-tb {
flex-direction: column;
}
.box-bt {
flex-direction: column-reverse;
}
.box-pack-center {
justify-content: center;
}
.day-week{
color:#ccc;
}
.box-pack-start {
justify-content: flex-start;
}
.box-pack-end {
justify-content: flex-end;
}
.box-pack-between {
justify-content: space-between;
}
.box-pack-around {
justify-content: space-around;
}
.box-align-center {
align-items: center;
}
.years-month{
color: #000;
}
.box-align-start {
align-items: flex-start;
}
.box-align-end {
align-items: flex-end;
}
.self-align-center {
align-self: center;
margin: 0 auto;
}
.self-align-start {
align-self: flex-start;
}
.self-align-end {
align-self: flex-end;
}
.self-align-stretch {
align-self: stretch;
}
.box-wrap {
flex-wrap: wrap;
}
.box-nowrap {
flex-wrap: nowrap;
}
.flex {
flex-grow: 1;
background: #fff;
}
.shrink {
flex-shrink: 1;
}
.bg {
background-image: linear-gradient(to bottom, #faefe7, #ffcbd7);
overflow: hidden;
}
.brown-color {
color: #784344;
}
.pink-color {
color: #ff629a;
}
.white-color {
color: #fff;
}
.fs24 {
font-size: 24rpx;
}
.fs28 {
font-size: 28rpx;
}
.fs32 {
font-size: 32rpx;
}
.fs36 {
font-size: 36rpx;
}
/*灰色显示 */
.grays{
color: #ccc;
}
以上是 小程序自定义日历效果 的全部内容, 来源链接: utcz.com/z/318797.html