小程序自定义日历效果


Posted in Javascript onDecember 29, 2018

本文实例为大家分享了小程序自定义日历展示的具体代码,供大家参考,具体内容如下

重点在于将数个月的日期拆分重组,然后再统一以月为输出。详细操作代码注释有说明。

<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;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
在JavaScript中通过URL传递汉字的方法
Apr 09 Javascript
window.open被浏览器拦截后的自定义提示效果代码
Nov 19 Javascript
实现变速回到顶部的JavaScript代码
May 09 Javascript
使用pjax实现无刷新更改页面url
Feb 05 Javascript
微信小程序开发之Tabbar实例详解
Jan 09 Javascript
微信小程序网络请求wx.request详解及实例
May 18 Javascript
对存在JavaScript隐式类型转换的四种情况的总结(必看篇)
Aug 31 Javascript
AngularJS对动态增加的DOM实现ng-keyup事件示例
Mar 12 Javascript
js中Generator函数的深入讲解
Apr 07 Javascript
Vue Extends 扩展选项用法完整实例
Sep 17 Javascript
vue的$http的get请求要加上params操作
Nov 12 Javascript
Vue 事件的$event参数=事件的值案例
Jan 29 Vue.js
微信小程序自定义带价格显示日历效果
Dec 29 #Javascript
微信小程序日历效果
Dec 29 #Javascript
微信小程序日历组件使用方法详解
Dec 29 #Javascript
微信小程序自定义可滑动日历界面
Dec 28 #Javascript
10行代码实现微信小程序滑动tab切换
Dec 28 #Javascript
微信小程序实现复选框效果
Dec 28 #Javascript
6行代码实现微信小程序页面返回顶部效果
Dec 28 #Javascript
You might like
3
2006/10/09 PHP
一个数据采集类
2007/02/14 PHP
基于php导出到Excel或CSV的详解(附utf8、gbk 编码转换)
2013/06/25 PHP
php自定义函数br2nl实现将html中br换行符转换为文本输入中换行符的方法【与函数nl2br功能相反】
2017/02/17 PHP
解决在laravel中leftjoin带条件查询没有返回右表为NULL的问题
2019/10/15 PHP
php5.3/5.4/5.5/5.6/7常见新增特性汇总整理
2020/02/27 PHP
KindEditor在php环境下上传图片功能集成的方法示例
2020/07/20 PHP
JQuery下的Live方法和$.browser方法使用代码
2010/06/02 Javascript
关于onchange事件在IE和FF下的表现及解决方法
2014/03/08 Javascript
JavaScript异步编程Promise模式的6个特性
2014/04/03 Javascript
AngularJS 路由详解和简单实例
2016/07/28 Javascript
JavaScript 栈的详解及实例代码
2017/01/22 Javascript
webpack4+Vue搭建自己的Vue-cli项目过程分享
2018/08/29 Javascript
vue路由--网站导航功能详解
2019/03/29 Javascript
基于redis的小程序登录实现方法流程分析
2020/05/25 Javascript
ant-design表单处理和常用方法及自定义验证操作
2020/10/27 Javascript
[01:08:30]DOTA2-DPC中国联赛 正赛 Ehome vs Elephant BO3 第一场 2月28日
2021/03/11 DOTA
基于windows下pip安装python模块时报错总结
2018/06/12 Python
详解TensorFlow查看ckpt中变量的几种方法
2018/06/19 Python
解决Python下imread,imwrite不支持中文的问题
2018/12/05 Python
python+opencv实现阈值分割
2018/12/26 Python
python字符串反转的四种方法详解
2019/12/02 Python
pandas针对excel处理的实现
2021/01/15 Python
纯CSS3代码实现switch滑动开关按钮效果
2016/08/30 HTML / CSS
店长岗位职责
2013/11/21 职场文书
优秀学生事迹材料
2014/02/08 职场文书
机械专业应届毕业生自荐书
2014/06/12 职场文书
交通志愿者活动总结
2014/06/27 职场文书
法人委托书
2014/07/31 职场文书
2014年职称评定工作总结
2014/11/26 职场文书
清明节文明祭祀倡议书
2015/04/28 职场文书
教师教育教学随笔
2015/08/15 职场文书
用基于python的appium爬取b站直播消费记录
2021/04/17 Python
python 模拟在天空中放风筝的示例代码
2021/04/21 Python
mysql 数据插入优化方法之concurrent_insert
2021/07/01 MySQL
Java 使用类型为Object的变量指向任意类型的对象
2022/04/13 Java/Android