小程序自定义日历效果


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 相关文章推荐
基于JQuery的asp.net树实现代码
Nov 30 Javascript
THREE.JS入门教程(1)THREE.JS使用前了解
Jan 24 Javascript
js实现弹窗插件功能实例代码分享
Dec 12 Javascript
JS实现让网页背景图片斜向移动的方法
Feb 25 Javascript
EasyUi combotree 实现动态加载树节点
Apr 01 Javascript
基于HTML5上使用iScroll实现下拉刷新,上拉加载更多
May 21 Javascript
jQuery实现公告新闻自动滚屏效果实例代码
Jul 14 Javascript
原生js实现简单的模态框示例
Sep 08 Javascript
使用clipboard.js实现复制功能的示例代码
Oct 16 Javascript
微信小程序获取位置展示地图并标注信息的实例代码
Sep 01 Javascript
Node登录权限验证token验证实现的方法示例
May 25 Javascript
Node实现搜索框进行模糊查询
Jun 28 Javascript
微信小程序自定义带价格显示日历效果
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
优化php效率,提高php性能的一些方法
2011/03/24 PHP
解析mysql中UNIX_TIMESTAMP()函数与php中time()函数的区别
2013/06/24 PHP
CI框架学习笔记(一) - 环境安装、基本术语和框架流程
2014/10/26 PHP
在Windows系统下使用PHP生成Word文档的教程
2015/07/03 PHP
PhpSpreadsheet设置单元格常用操作汇总
2020/11/13 PHP
EasyUi tabs的高度与宽度根据IE窗口的变化自适应代码
2010/10/26 Javascript
Jquery命名冲突解决的五种方案分享
2012/03/16 Javascript
javascript和HTML5利用canvas构建猜牌游戏实现算法
2013/07/17 Javascript
基于NodeJS的前后端分离的思考与实践(六)Nginx + Node.js + Java 的软件栈部署实践
2014/09/26 NodeJs
jQuery在header中设置请求信息的方法
2017/03/06 Javascript
Javascript实现页面滚动时导航智能定位
2017/05/06 Javascript
jQuery Easyui Treegrid实现显示checkbox功能
2017/08/08 jQuery
vue3.0 搭建项目总结(详细步骤)
2019/05/20 Javascript
深入剖析JavaScript instanceof 运算符
2019/06/14 Javascript
JS实现求字符串中出现最多次数的字符和次数示例
2019/07/05 Javascript
JavaScript面试中常考的字符串操作方法大全(包含ES6)
2020/05/10 Javascript
Python使用time模块实现指定时间触发器示例
2017/05/18 Python
Python使用filetype精确判断文件类型
2017/07/02 Python
Python实现JSON反序列化类对象的示例
2018/01/31 Python
django连接mysql配置方法总结(推荐)
2018/08/18 Python
对DataFrame数据中的重复行,利用groupby累加合并的方法详解
2019/01/30 Python
Python使用pymysql模块操作mysql增删改查实例分析
2019/12/19 Python
python selenium操作cookie的实现
2020/03/18 Python
Django-imagekit的使用详解
2020/07/06 Python
解决redis与Python交互取出来的是bytes类型的问题
2020/07/16 Python
详解Html5页面实现下载文件(apk、txt等)的三种方式
2018/10/22 HTML / CSS
美国女性运动零售品牌:Lady Foot Locker
2017/05/12 全球购物
大学毕业登记表自我鉴定
2013/10/09 职场文书
2014年大学生就业规划书
2014/04/04 职场文书
贷款担保申请书
2014/05/20 职场文书
派出所副所长四风问题个人整改措施思想汇报
2014/10/13 职场文书
社区文明倡议书
2015/04/28 职场文书
2015年村级财务管理制度
2015/08/04 职场文书
信息技术课教学反思
2016/02/23 职场文书
python 如何在 Matplotlib 中绘制垂直线
2021/04/02 Python
Python matplotlib 利用随机函数生成变化图形
2022/04/26 Python