最近需求要求实现一个用日历显示用户打卡记录的功能,百度google了微信小程序的组件,都没有找到合适的,索性就懒得找了,自己动手,丰衣足食。
下面先来看看日历组件的效果吧:
设计要求:
1、能够折叠日历组件
2、能够标记日期
3、能够根据左右滑动切换月份,并且刷新数据。
设计思路:
1、折叠可以通过添加移除class实现动画折叠。
2、每个日期都是一个格子,可以放时间,也可以放图标,只需要根据wx:if来控制是否显示图标和样式。
3、使用微信的原生组件swiper来实现左右滑动的效果,监听swiper切换并刷新数据。
组件代码如下:
index.js
Component({
properties: {
clockDatas: {
type: Array
}
},
data: {
showMore: false,
weekData: ['日', '一', '二', '三', '四', '五', '六'],
miniContent: [
///monthStatus:0-上月日期,1-本月日期,2-下月日期,isSignIn是否已签到,isToday当前日期是否是今天
{ id: 1, title: "26", monthStatus: 1, isSignIn: false, isToday: false }
],
largeContent: [],
today: "",
currentYear: "",
currentMonth: "",
currentDate: "",
lastSwiper: 0
},
observers: {
'clockDatas': function(data){
console.log("数据更新");
let changeDate = this.data.currentYear + "-" + this.data.currentMonth + "-1";
this.getLargeDate(changeDate);
}
},
ready: function () {
this.initCalendar();
},
methods: {
contentToggle(){
this.setData({
showMore: !this.data.showMore
})
},
//初始化日历
initCalendar(){
let dateObject = new Date(),
year = dateObject.getFullYear(),
month = dateObject.getMonth() + 1,
date = dateObject.getDate(),
today = year + '-' + this.zero(month) + '-' + this.zero(date);
this.setData({
today: today,
currentYear: year,
currentMonth: month,
currentDate: date
});
this.getMiniDate();
this.getLargeDate();
},
// 获取小日期
getMiniDate(){
let dateObject = new Date();
let toMonth = dateObject.getMonth() + 1;
let toDay = dateObject.getDate();
let toWeek = dateObject.getDay();
dateObject.setDate(dateObject.getDate() - toWeek);
let miniData = [];
for(let i=0;i<7;i++){
let currentDate = this.getFormatDate(dateObject);
let clockDate = this.data.clockDatas.filter((item) => item.date==currentDate.date);
let currentObj = {
title: currentDate.day,
monthStatus: (currentDate.month > toMonth ? 2 : (currentDate.month < toMonth ? 0 : 1)),
isSignIn: clockDate.length>0?true:false,
isToday: (currentDate.day==toDay ? true : false)
}
miniData.push(currentObj);
dateObject.setDate(dateObject.getDate()+1);
}
//console.log("小日期", miniData);
this.setData({
miniContent: miniData
});
},
// 获取大的日期
getLargeDate(dates){
let dateObject = dates ? new Date(dates) : new Date();
let toMonth = dateObject.getMonth() + 1;
let toDay = dateObject.getDate();
let toWeek = new Date(dateObject.getFullYear(), toMonth - 1, 1).getDay(); // 获取本月一号的星期
let toDates = 42;
dateObject.setDate(dateObject.getDate() - (toWeek + toDay - 1));
let largeData = [];
for (let i = 0; i < toDates; i++) {
let currentDate = this.getFormatDate(dateObject);
let clockDate = this.data.clockDatas.filter((item) => item.date==currentDate.date);
let currentObj = {
title: currentDate.day,
monthStatus: (currentDate.month > toMonth ? 2 : (currentDate.month < toMonth ? 0 : 1)),
isSignIn: clockDate.length>0?true:false,
isToday: (currentDate.date == this.data.today ? true : false)
}
largeData.push(currentObj);
dateObject.setDate(dateObject.getDate() + 1);
}
//console.log("大日期", largeData);
this.setData({
largeContent: largeData
});
},
getFormatDate(date){
let year = date.getFullYear(),
month = date.getMonth() + 1,
day = date.getDate();
let currentDate = year + "-" + this.zero(month) + "-" + this.zero(day);
return {
year: year,
month: month,
day: day,
date: currentDate
}
},
// 滑块改变事件
swiperChange(e){
let current = e.detail.current;
let lastSwiper = this.data.lastSwiper;
let status = current - lastSwiper;
if(status == -1 || status == 2){
//console.log("右滑");
this.setCurrentDate(0); //月份减一
}else if(status == 1 || status == -2){
//console.log("左滑");
this.setCurrentDate(1); //月份加一
}else{
console.log("其他");
}
let changeDate = this.data.currentYear + "-" + this.data.currentMonth + "-1";
//this.getLargeDate(changeDate);
this.triggerEvent('changeMonth',{year: this.data.currentYear, month: this.data.currentMonth});
this.setData({
lastSwiper: current
})
},
// 根据传入的参数加减月份
setCurrentDate(type){
let currentYear = Number(this.data.currentYear);
let currentMonth = Number(this.data.currentMonth);
if(type){
if(currentMonth==12){
currentYear = currentYear + 1;
currentMonth = 1;
}else{
currentMonth = currentMonth + 1;
}
}else{
if(currentMonth == 1){
currentYear = currentYear - 1;
currentMonth = 12;
}else{
currentMonth = currentMonth - 1;
}
}
this.setData({
currentYear: currentYear,
currentMonth: currentMonth
})
},
//补全0
zero: function (i) {
return i >= 10 ? i : '0' + i;
},
}
})
index.wxml
<view class="calendar">
<view class="week-container">
<block wx:for="{{weekData}}">
<view class="week-item">{{item}}</view>
</block>
</view>
<view class="calendar-container {{showMore?'large-active':''}}">
<block wx:if="{{!showMore}}">
<view class="mini-calendar">
<block wx:for="{{miniContent}}">
<view class="day-item {{item.monthStatus==1?'':'other-moth'}}">
<view class="day-title {{item.isSignIn?'sign-active':''}} {{item.isToday?'today':''}}">
{{item.title}}
</view>
<view wx:if="{{item.isSignIn}}" class="sign-icon">
<image class="image" src="../../images/clockin_ok.png"></image>
</view>
</view>
</block>
</view>
</block>
<block wx:elif="{{showMore}}">
<swiper class="swiper" circular bindchange="swiperChange">
<!-- 第一滑块 -->
<swiper-item>
<view class="large-calendar">
<block wx:for="{{largeContent}}">
<view class="day-item {{item.monthStatus==1?'':'other-moth'}}">
<view class="day-title {{item.isSignIn?'sign-active':''}} {{item.isToday?'today':''}}">{{item.title}}</view>
<view wx:if="{{item.isSignIn}}" class="sign-icon">
<image class="image" src="../../images/clockin_ok.png"></image>
</view>
</view>
</block>
<view class="month-show">
<text>{{currentYear}}年 {{currentMonth}}月</text>
</view>
</view>
</swiper-item>
<!-- 第二滑块 -->
<swiper-item>
<view class="large-calendar">
<block wx:for="{{largeContent}}">
<view class="day-item {{item.monthStatus==1?'':'other-moth'}}">
<view class="day-title {{item.isSignIn?'sign-active':''}} {{item.isToday?'today':''}}">{{item.title}}</view>
<view wx:if="{{item.isSignIn}}" class="sign-icon">
<image class="image" src="../../images/clockin_ok.png"></image>
</view>
</view>
</block>
<view class="month-show">
<text>{{currentYear}}年 {{currentMonth}}月</text>
</view>
</view>
</swiper-item>
<!-- 第三滑块 -->
<swiper-item>
<view class="large-calendar">
<block wx:for="{{largeContent}}">
<view class="day-item {{item.monthStatus==1?'':'other-moth'}}">
<view class="day-title {{item.isSignIn?'sign-active':''}} {{item.isToday?'today':''}}">{{item.title}}</view>
<view wx:if="{{item.isSignIn}}" class="sign-icon">
<image class="image" src="../../images/clockin_ok.png"></image>
</view>
</view>
</block>
<view class="month-show">
<text>{{currentYear}}年 {{currentMonth}}月</text>
</view>
</view>
</swiper-item>
</swiper>
</block>
<view class="bottom-toggle">
<view class="toggle-content" bindtap="contentToggle">
<view class="toggle-left"></view>
<view class="toggle-center">
<text class="iconfont {{showMore?'iconicon-test1':'iconicon-test3'}}"></text>
</view>
<view class="toggle-right"></view>
</view>
</view>
</view>
</view>
index.wxss
@import "../../utils/iconfont.wxss";
.calendar {
width: 100%;
text-align: center;
font-size: 28rpx;
padding: 0rpx 20rpx;
background: linear-gradient(to bottom, #ff6000, #ffbb59);
box-shadow: 0 0 3px #ccc;
}
/* 星期头部 */
.week-container{
width: 100%;
padding: 10rpx 0rpx;
display: flex;
align-items: center;
justify-content: space-around;
color: #ffffff;
}
.week-container .week-item{
flex: 1;
width: 100rpx;
text-align: center;
}
/* 星期头部 */
/* 主体 */
.calendar-container{
width: 100%;
height: 120rpx;
transition: all .25s;
position: relative;
}
.large-active{
height: 780rpx;
}
.bottom-toggle{
width: 100%;
height: 30rpx;
line-height: 30rpx;
position: absolute;
bottom: -30rpx;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
z-index: 9;
}
.bottom-toggle .toggle-content{
height: 30rpx;
width: 108rpx;
text-align: center;
position: relative;
}
.bottom-toggle .toggle-content .toggle-left{
width: 20rpx;
height: 40rpx;
transform: rotate(-30deg);
background-color: #ffbb59;
position: absolute;
left: -14rpx;
top: -12rpx;
}
.bottom-toggle .toggle-content .toggle-center{
width: 100%;
height: 100%;
color: #ffffff;
background-color: #ffbb59;
font-size: 42rpx;
line-height: 24rpx;
text-align: center;
}
.bottom-toggle .toggle-content .toggle-right{
width: 20rpx;
height: 40rpx;
transform: rotate(30deg);
background-color: #ffbb59;
position: absolute;
right: -14rpx;
top: -12rpx;
}
/* 主体 */
/* 收缩日历主体 */
.mini-calendar{
display: flex;
align-items: center;
justify-content: space-around;
color: #ffffff;
}
/* 收缩日历主体 */
/* 展开日历主体 */
.swiper{
height: 780rpx;
}
.large-calendar{
display: flex;
align-items: center;
justify-content: space-around;
flex-wrap: wrap;
color: #ffffff;
}
.large-calendar .month-show{
width: 100%;
height: 60rpx;
text-align: center;
color: #ffffff;
}
/* 展开日历主体 */
/* 公用样式 */
.day-item{
flex-shrink: 0;
width: 100rpx;
min-height: 100rpx;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
margin-bottom: 20rpx;
}
.other-moth{
color: #e2e2e2;
}
.today-item{
position: absolute;
width: 20rpx;
height: 20rpx;
border-radius: 50%;
}
.day-item .day-title{
width: 50rpx;
height: 50rpx;
line-height: 50rpx;
border-radius: 50%;
}
.day-item .sign-active{
background-color: rgba(255,255,255,0.3);
}
.day-item .today{
background-color: #ff6000;
}
.day-item .sign-icon{
width: 40rpx;
height: 40rpx;
margin-top: 10rpx;
}
.day-item .sign-icon .image{
width: 100%;
height: 100%;
}
/* 公用样式 */
父组件使用方法:
// wxml
<rwj-calendar clock-datas="{{clockData}}" bindchangeMonth="changeMonth"></rwj-calendar>
// js
data: {
clockData: [
{ date: "2020-06-01" },
{ date: "2020-06-02" },
{ date: "2020-06-03" },
{ date: "2020-06-04" }
],
},
// 日历组件月更改事件
changeMonth(e){
console.log("日历组件月改变事件",e);
this.setData({
clockData: [
{ date: "2020-05-11" },
{ date: "2020-05-12" },
{ date: "2020-05-23" },
{ date: "2020-05-24" }
],
})
},
完整代码:https://download.csdn.net/download/qq_41756580/12827602