最近想在在做的微信小程序加一个计时器功能,就是可以设置一个时间,可以开始倒计时,暂停,最终实现结果(图1,2所示),可能这个配色及样式有点糟糕毕竟css太难了 ,可以在这个基础上进行扩展,如果时间到了会弹出图片或者播放音乐等等
图1
图2
1. block.wxml编写,写出计时器大概骨架
wxml中编写出大体需要的组件,代码如下:
<!--index.wxml-->
<image class="bg" src="../../images/webp (2).webp"></image>
<view hidden="{{clockShow}}">
<view class="slider">
<slider min="1" max="60" show-value activeColor="#E7624F"
backgroundColor="#666666" value="{{time}}" bindchange="slideChange"></slider>
</view>
<view class="task_text">
<view class="task_title">选择一个任务</view>
<view class="task_desc">在接下来的{{time}}分钟内,您将专注做这件事</view>
</view>
<view class="task_cate">
<view wx:for="{{cateArr}}" class="cate_item" wx:key="cate" bindtap="clickCate"
data-index="{{index}}">
<view class="cate_icon"> <image src="../../images/{{item.icon}}.png"></image> </view>
<view class='cate_text {{index == cateActive ? "cate_text_active" : ""}}'>{{item.text}}</view>
</view>
<view class="start" bindtap="start">
开始专注
</view>
</view>
</view>
<view class="clock" hidden="{{!clockShow}}" style="height:{{clockHeight}}rpx">
<view class="progress">
<canvas canvas-id="progress_bg" class="progress_bg"></canvas>
<canvas canvas-id="progress_active" class="progress_active"></canvas>
<view class="progress_text">{{timeStr}}</view>
</view>
<view class="btns">
<view class="okBtn" bindtap="ok" wx:if="{{okShow}}">返回</view>
<view class="pauseBtn" bindtap="pause" wx:if="{{pauseShow}}">暂停</view>
<view class="continueCancelBtn" wx:if="{{continueCancelShow}}">
<view class="continueBtn" bindtap="continue">继续</view>
<view class="cancelBtn" bindtap="cancel">放弃</view>
</view>
</view>
</view>
2. block.wxss编写,写出计时器大概骨架
block.wxss对wxml中的组件编写样式,实现好看背景及布局,代码如下:
.adv1{
width: 100%;
height: 900rpx;
background: url('/img/ba3.png') no-repaeat 0 0;
background-size: contain;
}
.adv-img{
width: 100%;
height: 900rpx;
position: absolute;
}
.tiaoguo{
font-size: 25rpx;
background-color: wheat;
border-radius: 80rpx;
display: inline-block;
margin-left: 10rpx;
position: absolute;
z-index: 999;
right: 25rpx;
top: 850rpx;
padding-left: 10rpx;
padding-right: 10rpx;
}
button{
border-radius: 18rpx;
width: 220rpx;
background-color: #EECBAD;
color: #8B5742;
margin-top: 38rpx;
font-size: 33rpx;
}
.text2{
width: 100%;
height: 100%;
display: flex;
justify-content: center;
margin-top: 23rpx;
font-size: 28rpx;
}
.bg{
width: 100%;
height: 100%;
position:fixed;
background-size:100% 100%;
z-index: -1;
filter: blur(10rpx);
}
.silder{
width: 650rpx;
margin: 40rpx auto;
}
.task_text{
height: 120rpx;
margin: 40rpx auto;
text-align: center;
}
.task_text .task_title{
font-size: 35rpx;
height: 70rpx;
line-height: 70rpx;
}
.task_text .task_desc{
font-size: 30rpx;
height: 50rpx;
line-height: 50rpx;
color: #999999;
}
.task_cate{
width: 660rpx;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}
.task_cate .cate_item{
width: 220rpx;
height: 130rpx;
text-align: center;
margin-bottom: 50rpx;
}
.task_cate .cate_item .cate_icon{
height: 70rpx;
}
.task_cate .cate_item .cate_icon image{
width: 50rpx;
height: 50rpx;
}
.task_cate .cate_item .cate_text{
height: 60rpx;
line-height: 60rpx;
font-size: 30rpx;
}
.task_cate .cate_item .cate_text_active{
color: #e41749;
}
.start{
width: 280rpx;
height: 90rpx;
line-height: 90rpx;
text-align: center;
margin: 40rpx auto;
border: 2rpx solid #e41749;
color: #e41749;
border-radius: 20rpx;
}
.clock{
overflow: hidden;
background: #8ac6d1;
}
.progress{
width: 400rpx;
height: 400rpx;
/* background: orange; */
margin: 140rpx auto;
position: relative;
}
.progress .progress_bg,.progress_active{
position: absolute;
left: 0;
top: 0;
width: 400rpx;
height: 400rpx;
}
.progress .progress_text{
width: 160rpx;
height: 60rpx;
line-height: 60rpx;
font-size: 30rpx;
color: #ffffff;
text-align: center;
position: absolute;
left: 120rpx;
top: 170rpx;
}
.btns .okBtn, .btns .pauseBtn, .btns .continueBtn, .btns .cancelBtn{
width: 280rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
color: #ffffff;
border: 3rpx solid #ffffff;
border-radius: 20rpx;
margin: 0 auto 20rpx auto;
}
3. block.js编写,写出计时器大概骨架
block.js动态绑定数据,实现开始计时,以及暂停计时等功能,代码如下:
//获取util实例
const app = getApp()
const util = require('../../utils/util.js')
Page({
data: {
clockShow:false,
clockHeight:0,
time:'5',
mTime:300000,
timeStr:'05:00',
rate:'',
timer:null,
cateArr:[
{
icon: 'work',
text: '工作'
},
{
icon: 'study',
text: '学习'
},
{
icon: 'think',
text: '思考'
},
{
icon: 'write',
text: '写作'
},
{
icon: 'sport',
text: '运动'
},
{
icon: 'read',
text: '阅读'
}
],
cateActive:'0',
okShow:false,
pauseShow:true,
continueCancelShow:false
},
onLoad: function() {
var res = wx.getSystemInfoSync();
var rate = 750 / res.windowWidth;
console.log(rate);
this.setData({
rate:rate,
clockHeight:rate * res.windowHeight
})
},
slideChange:function(e){
this.setData({
time:e.detail.value
})
},
clickCate:function(e){
this.setData({
cateActive:e.currentTarget.dataset.index
})
},
start:function(){
this.setData({
clockShow:true,
mTime:this.data.time*60*1000,
timeStr:parseInt(this.data.time) >= 10 ? this.data.time+':00' :
'0' + this.data.time+':00'
})
this.drawBg();
this.drawActivve();
},
drawBg:function(){
var lineWidth = 6 / this.data.rate;//px
var ctx = wx.createCanvasContext('progress_bg');
ctx.setLineWidth(lineWidth);
ctx.setStrokeStyle('#000000');
ctx.setLineCap('round');
ctx.beginPath();
ctx.arc(400/this.data.rate/2,400/this.data.rate/2,400/this.data.rate/2-2*lineWidth,0,2*Math.PI,false);
ctx.stroke();
ctx.draw();
},
// 动态画圆
drawActivve:function(){
var _this = this;
var timer = setInterval(function(){
//1.5-3.5
var angle = 1.5 + 2*(_this.data.time*60*1000 - _this.data.mTime)/
(_this.data.time*60*1000);
var currentTime = _this.data.mTime - 100;
_this.setData({
mTime:currentTime
});
if(angle < 3.5){
if(currentTime % 1000 == 0){
var timeStr1 = currentTime / 1000;// s
var timeStr2 = parseInt(timeStr1 / 60);// m
var timeStr3 = (timeStr1 - timeStr2*60) >= 10 ? (timeStr1 - timeStr2*60) :
'0'+(timeStr1 - timeStr2*60);
var timeStr2 = timeStr2 >= 10 ? timeStr2 : '0'+timeStr2;
_this.setData({
timeStr:timeStr2+':'+timeStr3
})
}
var lineWidth = 6 / _this.data.rate;//px
var ctx = wx.createCanvasContext('progress_active');
ctx.setLineWidth(lineWidth);
ctx.setStrokeStyle('#ffffff');
ctx.setLineCap('round');
ctx.beginPath();
ctx.arc(400/_this.data.rate/2,400/_this.data.rate/2,400/_this.data.rate/2-2*lineWidth,
1.5*Math.PI,angle*Math.PI,false);
ctx.stroke();
ctx.draw();
}else{
var logs = wx.getStorageSync('logs') || [];
logs.unshift({
date:util.formatTime(new Date),
cate:_this.data.cateActive,
time:_this.data.time
});
wx.setStorageSync('logs', logs);
_this.setData({
timeStr:'00:00',
okShow:true,
pauseShow:false,
continueCancelShow:false
});
clearInterval(timer);
}
},100)
_this.setData({
timer:timer
})
},
pause:function(){
clearInterval(this.data.timer);
this.setData({
pauseShow:false,
continueCancelShow:true,
okShow:false
})
},
continue:function(){
this.drawActivve();
this.setData({
pauseShow:true,
continueCancelShow:false,
okShow:false
})
},
cancel:function(){
clearInterval(this.data.timer);
this.setData({
pauseShow:true,
continueCancelShow:false,
okShow:false,
clockShow:false
})
},
ok:function(){
clearInterval(this.data.timer);
this.setData({
pauseShow:true,
continueCancelShow:false,
okShow:false,
clockShow:false
})
}
})
4. 在微信小程序项目根目录下新建utils文件夹,放置utils.js的文件
utils文件夹一定在项目根目录下(图3所示),utils.js文件是对日期格式进行处理,代码如下:
图3
utils.js代码:
const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
return [year, month, day].map(formatNumber).join('-') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
const formatNumber = n => {
n = n.toString()
return n[1] ? n : '0' + n
}
module.exports = {
formatTime: formatTime
}
到这里,我们就可以实现微信小程序简单的计时器,你也可以在这个基础上实现一些更复杂的更好看的功能。