最近想在在做的微信小程序加一个计时器功能,就是可以设置一个时间,可以开始倒计时,暂停,最终实现结果(图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
}

到这里,我们就可以实现微信小程序简单的计时器,你也可以在这个基础上实现一些更复杂的更好看的功能。

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

微信小程序自定义计时器功能的更多相关文章

  1. 微信小程序之html5 canvas绘图并保存到系统相册

    这篇文章主要介绍了微信小程序之html5 canvas绘图并保存到系统相册,需要的朋友可以参考下

  2. xcode – 当NSMenu在Swift中打开时,NSTimer不会触发

    这不是什么大不了的事,但我不希望用户与会话混淆,如果他们看到计时器停机就会挂起.解决方法您只需将计时器添加到主runloop,如下所示:斯威夫特3Swift2.x

  3. xcode – Swift计时器,以毫秒为单位

    我想每毫秒更改一次计时器,但它不能按预期工作.结果是计时器在毫秒部分(00:100)中更改为100,然后更改为01:00=40实际秒邓肯方法:结果:456680125.54539第一次打印解决方法正如Martin在评论中所说,定时器的分辨率为50-100毫秒(0.05到0.1秒).尝试运行时间间隔短于此的计时器将无法提供可靠的结果.此外,计时器不是实时的.它们取决于它们所连接的运行循环,如果运行循

  4. 在iOS应用程序中使用dispatch_source_t无法在GCD块中运行计时器

    我想在GCD块中创建一个定时器来将其用作后台任务.但是,当我看到定时器火从来没有.这是我的代码:那么这是什么问题?解决方法您必须使您的dispatch_source_t成为一个类属性或实例变量,因此它不会超出范围.如果你这样做,你的代码可以正常工作,例如:另请注意,如果您希望在启动后台进程后更改BOOL的值,您可能也希望将其设置为类属性,如上所示.我也将其更名为观察消息,使其目的更为简单.

  5. 显示在视图控制器之间保留的iOS应用程序的计时器

    我一直试图通过使用NSTimer在我的应用程序的左下角显示一个计时器,并将“经过时间”显示为左下角的UILabel,但它并没有为我工作.计时器实际上工作,但我不能让它由按钮触发.我正在尝试让计时器继续运行,而不是在进入下一个storyboard/xib文件时重新启动.解决方法要在按下按钮时实现计时器操作,您需要在IBAction方法上编写它,如:要存储以前的值,可以使用NSUserDefaults或sqlite数据库.为此,我建议NSUserDefaults.更改aTime方法,如:

  6. ios – NSTimer不会因无效而停止

    我像这样添加计时器这是我班级的NSTimer属性.然后我点击按钮就停止它fbt它是我班级的实例.如果我只调用invalidate然后它不会停止,但如果我将它设置为nil然后我得到了EXC_BREAKPOINT这里选择器中的repeatTim方法的代码我试着调用init并使其无效它也不会停止计时器.解决方法阅读NSTimer的文档:Therearethreewaystocreateatimer:Us

  7. ios – 在发射开始后更改CAEmitterLayer的CAEmitterCell属性

    当我第一次设置发射器时,我可以这样做:但是说我创建了一个5秒后触发的计时器,我这样做:计时器触发,但CAEmitterCell的yacceleration不会更改.或者至少屏幕上的粒子发射没有任何变化.如何让CAEmitterCell尊重我对其属性所做的更改?解决方法这不是很明显,但这是解决方案:“cell”是这里给出的名字:

  8. ios – 如何在进入后台后杀死NSTimer并在应用程序恢复活动后创建新的计时器?

    或许我应该把所有与计时器相关的代码放在AppDelegate.swift中?

  9. ios – 如何维护两个不同设备之间的时钟会话?

    我正在研究iOS应用程序,它需要在接受两个设备用户时在两个设备之间维持时钟计时器会话?但我不确定如何在两台设备上都没有时间缺陷的情况下实现这一目标?

  10. ios – 如何在Swift中实现非常精确的计时?

    我正在开发一个具有琶音/排序功能的音乐应用程序,需要很高的计时准确性.目前,使用“Timer”我已经达到了平均抖动约为5ms的精度,但最大抖动约为11ms,这对于8号,16号音符的快速琶音来说是不可接受的.特别是第32条.我已经读过’CAdisplayLink’比’Timer’更准确,但由于它的准确度限制在1/60秒,看起来它的准确性不如我用Timer实现了.潜入CoreAudio是实现我想要的唯一途径吗?还有其他方法可以实现更精确的计时吗?

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部