前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >🥬 🐶的uniapp学习之🦌 【计时器】

🥬 🐶的uniapp学习之🦌 【计时器】

作者头像
用户4793865
发布2023-01-12 15:14:22
1.5K0
发布2023-01-12 15:14:22
举报
文章被收录于专栏:前端小菜鸡yym前端小菜鸡yym

「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战

【前言】 我们这篇文章打算先画出页面的大概样式,具体录音功能下篇文章实现。

uView

这个并不是官方开发的第三方UI,是一个大佬开发的。现在使用的很广泛。 官网 💻

安装

我这里使用的是npm安装。如果是纯的uniapp项目,是没有包管理器package.json的,更没有node_modules的。

初始化

代码语言:javascript
复制
 npm init -y

初始化之后就会有package.json文件了

开始安装

新打开一个终端,执行命令

代码语言:javascript
复制
npm install uview-ui

📢

目前(2020-05-06)不支持通过cnpm安装uView

并且由于uView使用easycom模式,让您无需引入组件即可直接使用,但是此功能需要Hbuilder X 2.5.5及以上版本才支持。(类似于)

配置一下

像Vue项目引用第三方组件库一样,在main.js中引入 然后 Vue.use 使用

代码语言:javascript
复制
import uView from "uview-ui"; 
Vue.use(uView);

然后再去uni.scss中 在全局的CSS中加入

代码语言:javascript
复制
@import 'uview-ui/theme.scss';

最后在page.json配置文件中添加easycom

代码语言:javascript
复制
"easycom": {
            "^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
    },
"pages": [

      ]

然后测试一下,最方便的就是加入按钮

代码语言:javascript
复制
<u-button shape="square" type="success">乌啼</u-button>

如下:引入成功

实现录音器效果

步入正题,我想实现一个录音器。如下图:

需求

  1. 最上部,在计时的时候是一个动画效果,涟漪波纹效果。在停止计时的时候是话筒。
  2. 中间是 计时器 分:秒:毫秒
  3. 底部是三个按钮:第一个是重置按钮、第二个是开始和结束按钮(初始按钮是开始按钮中间是圆形,开始之后按钮是停止按钮中间是正方形)。第三个按钮是暂停和继续按钮,初始是播放按钮 ▶️,当开始录制后变为暂停⏸按钮。

顶部

主要是一个涟漪效果和话筒图标的切换

html部分

代码语言:javascript
复制
 <u-row gutter="16"> 
   <u-col span="12"> 
    <view v-if="pendingBtn==false" class="waves"> 
    </view> 
    <view v-if="pendingBtn==true" class="waves_stop"> 
     <u-icon name="mic" size="100"></u-icon> 
    </view> 
   </u-col> 
  </u-row>
  • <u-row>是UView栅格化布局的行。gutter:栅格间隔,左右各为此值的一半,单位rpx。
  • <u-col>是列,栅格占据的列数,总12等分。
  • 使用了一个变量 pendingBtn 来判断是哪种状态
  • 然后根据不同的类名来展示不同的效果定义数据
代码语言:javascript
复制
export default {
     data() {
            return {
                pendingBtn: true,
                }
            }
      }    

样式

这个地方把后面能用到的样式也都放在这了。

涟漪主要是添加了animation动画效果

代码语言:javascript
复制
<style>
    .wrap {
        background-color: #193443;
        height: 100%
    }

    body {
        width: 100%;
        height: 100%;
        background: #142c3a;
        margin: 0px;
        overflow: hidden;
    }

    .waves {
        position: relative;
        top: 50%;
        left: 44%;
        width: 250rpx;
        height: 250rpx;
        margin-left: 0px;
        margin-top: 200rpx;
        border-radius: 50%;
        /* padding-top:100rpx; */
        -webkit-backface-visibility: hidden;
    }

    .wave,
    .waves:before,
    .waves:after {
        position: absolute;
        background: white;
        margin-left: 0px;
        margin-top: 0px;
        width: 50px;
        height: 50px;
        content: "";
        display: block;
        border-radius: 50%;
        -webkit-backface-visibility: hidden;
    }

    .waves:before {
        animation: wave-animate 3s infinite ease-out;
    }

    .waves:after {
        opacity: 0;
        animation: wave-animate 3s 1.5s infinite ease-out;
    }

    .waves_stop {
        display: flex;
        background-color: #e0f2ea;
        width: 250rpx;
        height: 250rpx;
        margin-left: 33%;
        margin-top: 200rpx;
        border-radius: 50%;
        padding: 80rpx;
    }
        @keyframes wave-animate {
        0% {
            transform: scale(0);
            opacity: 1;
            transform-origin: center;
        }

        100% {
            transform: scale(3);
            opacity: 0;
            transform-origin: center;
        }
    }

    .timeStep {
        height: 100rpx
    }

    .startBtn {
        border-radius: 50%;
        width: 90rpx;
        height: 90rpx;
        border: 8rpx solid #ffffff;
        background-color: #f4f1f1;
        justify-content: center; //子元素水平居中
        align-items: center; //子元素垂直居中
        display: flex;

    }

    .circl {
        width: 50rpx;
        height: 50rpx;
        border-radius: 50%;
        background-color: red;
    }

    .square {
        width: 45rpx;
        height: 45rpx;
        background-color: red;
    }
        </style>

中间计时器

html

image.png
image.png

因为时间的这种格式,所以我进行了几个判断 对于分,当小于10的时候补个0占位。 对于秒,同样是补个0占位 对于毫秒,当时0的时候补两个0

代码语言:javascript
复制
    <!-- 第二行 计时器 -->
  <u-row gutter="16">
    <u-col span="12" class="timeStep" style="color: white;font-size:30px;text-align: center;height:400rpx;padding-top:40rpx">
        <span v-if="minute<10">0{{minute}}:</span>
        <span v-else>{{minute}}:</span>
        <span v-if="mill<10">0{{mill}}</span>
        <span v-else>{{mill}}</span> 
        <span v-if="millisecond==0">:00{{millisecond}}</span>
        <span v-else>:{{millisecond}}</span>		
    </u-col>
 </u-row>

setInterval()

计时需要使用setInterval()方法,setInterval()有两个参数,

  • 第一个参数是要执行的函数
  • 第二个参数是多久执行一次,单位是毫秒。[1m=1000ms]
代码语言:javascript
复制
    this.init = setInterval(this.timer, 100)

把函数赋值给一个变量,相当于给这个计时器绑定了唯一id,当我们要停止这个计时的时候通过这个id来停止。

clearInterval()

停止计时器需要clearInterval()方法,将我们定义的setInterval()函数对应变量传给它,来停止计时。

开始暂停继续结束 计时器

  • 定义好三个变量 分:minute 秒:mill 毫秒:millisecond
  • 开始时 执行setInterval(),并赋值给init变量。
  • 暂停时 执行clearInterval(),将刚才的init对应的计时器清除掉。但是对应的分 秒 毫秒 值还在。
  • 继续时 执行setInterval(),还要给它赋值给init。
  • 结束时 执行clearInterval(),销毁init 三个变量都清零。 然后具体代码实现我们在下面结合按钮一起讲。

最后底部按钮

html部分

代码语言:javascript
复制
<!-- 第三行 按钮 -->
        <!-- 重置按钮 -->
        <u-row gutter="16">
            <u-col span="3" offset="2">
                <u-icon name="reload" size="53rpx" color="white" @click="touchReset"></u-icon>
            </u-col>
            <u-col span="2" style="padding-left:13rpx;">
                <!-- 开始结束按钮 -->
                <view class="startBtn" @click="status==0?touchStart():touchStop()">
                    <!-- 按钮状态为0是圆形-->
                    <view v-if="status===0" class="circl">
                    </view>
                    <!-- 按钮状态 除了0 是正方形-->
                    <view v-if="status!=0" class="square">
                    </view>
                </view>
            </u-col>
            <!-- 暂停 继续 -->
            <u-col span="3" offset="2">
                <u-icon v-if="pendingBtn==false"  name="pause" size="50rpx" color="white" @click="touchpending() ">
                </u-icon>
                <u-icon v-if="pendingBtn==true" :style="{'pointer-events':status==0?'none':''}" name="play-right" size="50rpx" color="white" @click="status==0?a():touchpending()">
                </u-icon>
            </u-col>
        </u-row>
  • 重置按钮 <u-icon>是UView的图标,name对应不同的图标,size是图标大小,color是图标颜色。点击重置执行函数touchReset() 清零了时分秒,并且销毁了init// 点击重置按钮 touchReset:function(){ // 将时分秒清零 this.minute = 0 this.mill = 0 this.millisecond = 0 clearInterval(this.init) }
  • 开始结束按钮 使用了一个阴影效果样式请看.startBtn

内部的 ○ 和 □ 的切换, ○ 和 □ 的切换根据变量status[0:未开始 1:开始 2:暂停 3:继续 4:结束 ]。 当未开始时时○,其他状态都是□

当status是0时点击按钮执行touchStart()

代码语言:javascript
复制
// 点击开始按钮
touchStart: function() {
        // 开始后 把status变为1:开始 
    this.status = 1
        // 执行计时
    this.init = setInterval(this.timer, 100)
    // 这个变量用于:在未开始前暂停继续按钮禁止点击 true是禁止
        this.pendingBtn = false
    },

当status不是0️⃣ 的时候,点击此按钮,执行touchStop()

代码语言:javascript
复制
// 点击结束按钮
touchStop: function() {		
    this.pendingBtn = true
    clearInterval(this.init)
},
  • 暂停继续按钮 在页面初始加载的时候是继续播放按钮(pendingBtn是true)并且status是0也就是未开始时时不可点击的,但图标没有disabled属性,所以使用了pointer-events:none 属性来实现不可点击效果。但是点击它,它依旧执行了,所以我在点击的时候又加了个判断:当status是0时执行一个空函数,当不是0时执行touchpending()

当点击开始按钮后变为暂停按钮(pendingBtn是false),执行touchpending()。

代码语言:javascript
复制
// 点击暂停按钮
touchpending: function() {
        // 切换状态
    this.pendingBtn = !this.pendingBtn
    // 清除掉计时器
    clearInterval(this.init)
        // 继续时创建新的计时器
    this.pendingBtn == false ?
    this.init = setInterval(this.timer, 100) : ''
    },

完整代码

代码语言:javascript
复制
<template>
    <view class="wrap">
        <!-- 第一行 波纹 -->
        <u-row gutter="16">
            <u-col span="12">
                <!--  -->
                <view v-if="pendingBtn==false" class="waves">
                </view>
                <view v-if="pendingBtn==true" class="waves_stop">
                    <u-icon name="mic" size="100"></u-icon>
                </view>
            </u-col>
        </u-row>
        <!-- 第二行 计时器 -->
        <u-row gutter="16">
            <u-col span="12" class="timeStep"
                style="color: white;font-size:30px;text-align: center;height:400rpx;padding-top:40rpx">
                <span v-if="minute<10">0{{minute}}:</span>
                <span v-else>{{minute}}:</span>
                <span v-if="mill<10">0{{mill}}</span>
                <span v-else>{{mill}}</span>
                <span v-if="millisecond==0">:00{{millisecond}}</span>
                <span v-else>:{{millisecond}}</span>

            </u-col>
        </u-row>
        <!-- 第三行 按钮 -->
        <u-row gutter="16">
            <u-col span="3" offset="2">
                <u-icon name="reload" size="53rpx" color="white" @click="touchReset"></u-icon>
            </u-col>
            <u-col span="2" style="padding-left:13rpx;">
                <!-- 开始结束按钮 -->
                <view class="startBtn" @click="status==0?touchStart():touchStop()">
                    <!-- 按钮状态为0是圆形-->
                    <view v-if="status===0" class="circl">
                    </view>
                    <!-- 按钮状态 除了0 是正方形-->
                    <view v-if="status!=0" class="square">
                    </view>
                </view>
            </u-col>
            <!-- 暂停 继续 -->
            <u-col span="3" offset="2">
                <u-icon v-if="pendingBtn==false" name="pause" size="50rpx" color="white" @click="touchpending() ">
                </u-icon>
                <u-icon v-if="pendingBtn==true" :style="{'pointer-events':status==0?'none':''}" name="play-right"
                    size="50rpx" color="white" @click="status==0?a():touchpending()">
                </u-icon>
            </u-col>
        </u-row>
    </view>
</template>

<script>

    export default {
        data() {
            return {
                // 0:未开始 1:开始 2:暂停 3:继续 4:结束 
                status: 0,
                playStatus: 0,
                pendingBtn: true,
                init: '',
                millisecond: 0,
                mill: 0,
                minute: 0

            }
        },
        onLoad() {

        },
        methods: {
            // 点击开始按钮
            touchStart: function() {
                // 开始后 把status变为1:开始 
                this.status = 1
                this.init = setInterval(this.timer, 100)
                // 这个变量用于:在未开始前暂停继续按钮禁止点击 true是禁止
                this.pendingBtn = false
            },
            // 点击暂停按钮
            touchpending: function() {
                this.pendingBtn = !this.pendingBtn
                // 清除掉计时器
                clearInterval(this.init)
                 // 继续时创建新的计时器
                this.pendingBtn == false ?
                    this.init = setInterval(this.timer, 100) : ''
            },
            // 点击结束按钮
            touchStop: function() {
                this.pendingBtn = true
                clearInterval(this.init)

            },
            // 点击重置按钮
            touchReset: function() {
                // 将时分秒清零
                this.minute = 0
                this.mill = 0
                this.millisecond = 0
                clearInterval(this.init)

            },
            changeRecordStart: function() {
                this.start = !this.start
                this.recordStart()
            },
            changeFinish: function() {
                this.finish += 1
                this.changeRecordStart()
                if (this.finish == 3) {
                    console.log("录音结束了")
                }
            },

            // 计时器
            timer: function() {
                this.millisecond += 100
                if (this.millisecond >= 1000) {
                    this.millisecond = 0;
                    this.mill = this.mill + 1;
                }
                if (this.mill >= 60) {
                    this.mill = 0;
                    this.minute = this.minute + 1;
                }

            }
            

        }


    }
</script>

<style>
    .wrap {
        background-color: #193443;
        height: 100%
    }

    body {
        width: 100%;
        height: 100%;
    }

    body {
        background: #142c3a;
        margin: 0px;
        overflow: hidden;
    }

    .waves {
        position: relative;
        /* background-image: url(../../static/MV.png); */
        top: 50%;
        left: 44%;
        width: 250rpx;
        height: 250rpx;
        margin-left: 0px;
        margin-top: 200rpx;
        border-radius: 50%;
        /* padding-top:100rpx; */
        -webkit-backface-visibility: hidden;
    }

    .wave,
    .waves:before,
    .waves:after {
        position: absolute;
        background: white;
        margin-left: 0px;
        margin-top: 0px;
        width: 50px;
        height: 50px;
        content: "";
        display: block;
        border-radius: 50%;
        -webkit-backface-visibility: hidden;
    }

    .waves:before {
        animation: wave-animate 3s infinite ease-out;
    }

    .waves:after {
        opacity: 0;
        animation: wave-animate 3s 1.5s infinite ease-out;
    }

    .waves_stop {
        display: flex;
        background-color: #e0f2ea;
        width: 250rpx;
        height: 250rpx;
        margin-left: 33%;
        margin-top: 200rpx;
        border-radius: 50%;
        padding: 80rpx;
    }

    @keyframes wave-animate {
        0% {
            transform: scale(0);
            opacity: 1;
            transform-origin: center;
        }

        100% {
            transform: scale(3);
            opacity: 0;
            transform-origin: center;
        }
    }

    .timeStep {
        height: 100rpx
    }

    .startBtn {
        border-radius: 50%;
        width: 90rpx;
        height: 90rpx;
        border: 8rpx solid #ffffff;
        background-color: #f4f1f1;
        justify-content: center; //子元素水平居中
        align-items: center; //子元素垂直居中
        display: flex;

    }

    .circl {
        width: 50rpx;
        height: 50rpx;
        border-radius: 50%;
        background-color: red;
    }

    .square {
        width: 45rpx;
        height: 45rpx;
        background-color: red;
    }
</style>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-11-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • uView
  • 实现录音器效果
    • 需求
      • 顶部
        • html部分
        • 样式
      • 中间计时器
        • html
        • setInterval()
        • clearInterval()
        • 开始暂停继续结束 计时器
      • 最后底部按钮
        • html部分
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档