美文网首页
手把手教你实现振动记录器

手把手教你实现振动记录器

作者: 思跃喵 | 来源:发表于2022-09-20 23:29 被阅读0次

    概述

    本文只涉及实现及代码讲解,不涉及具体技术的讲解,并尽量每一行代码都有详尽的注释,先实现,后积累。

    前端 - 入门级教程 - 简易振动记录器

    本文教大家实现一个简易的振动记录器。包括 短振动、长振动、振动录制开始/停止功能、播放功能,分享功能等

    技术栈使用 uniapp-vue3 版本,工具使用 HbuilderX,真机App调试,微信小程序调试;

    效果如下图:


    fdd269a738aaa2d3a23ed54df227ef0b.png

    分享效果如下图:


    0f5ae1f36e952d10c41882703c4fd3e5.png

    准备工作

    1. 安装 HbuilderX 最新版 https://www.dcloud.io/hbuilderx.html
    2. 安装 微信开发者工具 https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
    3. 打开HbuilderX 文件 - 新建 - 项目,新增一个uniapp项目,选择vue3版本
    c1f45df18032717dbb58af8fcf344265.png

    代码编写

    直接修改新建项目中的 /pages/index/index.vue 文件即可

    整体结构

    <template>
      
    </template>
    <script setup>
      
    </script>
    <style lang="scss" scoped>
      
    </style>
    

    <template>部分

    <template>
        <view class="content">
            <!-- 一个在抖动的图片 class 里面的shake类是一个左右振动的动画 -->
            <image class="logo shake" src="/static//vibrate.jpg"></image>
            
            <!-- 提示信息 -->
            <uni-title type="h1" title="点击下方按钮让手机振动"></uni-title>
    
            <!-- 短振动按钮,点击调用一次短震动,如果正在录制,那么往记录信息里面加一条数据 -->
            <button @click="onShortVibrate" type="primary">短振动</button>
            
            <!-- 长振动按钮,点击调用一次长振动,如果正在录制,那么往记录信息里面加一条数据 -->
            <button @click="onLongVibrate" type="primary">长振动</button>
            
            <!-- 提示信息 -->
            <uni-title type="h1" title="点击开始/停止录制"></uni-title>
            <uni-title type="h1" title="上方两个按钮的震动记录"></uni-title>
            
            <!-- 开始/停止录制振动按钮,点击之后开始或者停止振动 -->
            <button @click="onStartRecord" type="warn">{{vibrate.recordStatus ? '停止' : '开始'}}录制振动</button>
            
            <!-- 播放已经录制的振动 -->
            <button @click="onPlayRecord" :type="vibrate.isShowing ? 'default' : 'primary'">{{vibrate.isShowing ? '播放中...' : '播放振动'}}</button>
            
            <!-- 分享按钮 小程序中必须要有 open-type="share" -->
            <button  open-type="share">分享</button>
        </view>
    </template>
    

    <script setup> 部分

    <script setup>
        import {
            reactive
        } from "vue";
    
        // 来自官方文档的用法,引入分享的监听
        import {
            onShareAppMessage
        } from '@dcloudio/uni-app'
    
        // 震动状态
        const vibrate = reactive({
            // 用来延时控制动画,暂时不使用,会导致振动接口调用延迟
            status : "stop",
            
            // 如果要做多个录制的记录,这里放要展示的录制信息
            records: [],
            
            // 当前录制的数据
            // [{time:0,type:'short/long/stop'}] : time:相对时间
            nowRecords:[],
            
            // 是否正在录制中
            recordStatus : false,
            
            // 开始录制的时间戳
            startTime:0,
            
            // 是否在演示模式
            isShowing:false,
            
            // 一分钟录制限制
            limitTimer:null
            
        })
    
        // 点击短震动
        const onShortVibrate = () => {
            // 不在演示模式,并且正在录制中,演示模式时不加记录
            if(! vibrate.isShowing && vibrate.recordStatus){
                // 向当前录制的振动信息里面放一条新的数据
                vibrate.nowRecords.push({
                    time: new Date().getTime() - vibrate.startTime,
                    type : 'short'
                })
            }
            // 调用短震动
            uni.vibrateShort(); 
        }
        
        const onLongVibrate = () => {
            // 不在演示模式,并且正在录制中,演示模式时加记录
            if(! vibrate.isShowing && vibrate.recordStatus){
                // 向当前录制的振动信息里面放一条新的数据
                vibrate.nowRecords.push({
                    time: new Date().getTime() - vibrate.startTime,
                    type : 'long'
                })
            }
            // 调用长振动
            uni.vibrateLong();
        }
        
        // 开始/停止录制振动
        const onStartRecord = () => {
            // 如果正在录制中,那么停止录制
            if(vibrate.recordStatus){
                // 结束时间是点击按钮的时候,并不是点击确认停止的时候,所以放在这里
                let stopTime = new Date().getTime();
                // 调起一个交互框,询问是否需要停止录制
                uni.showModal({
                    title:"提示",
                    content:"确认停止录制吗?",
                    success: (res) => {
                        // 如果点击的是确认按钮
                        if(res.confirm === true){
                            // 此时停止记录,并把停止时间放进去
                            if(vibrate.nowRecords.length === 0){
                                uni.showToast({
                                    icon:"error",
                                    title:"至少振动一次"
                                })  
                                return;
                            }
                            // 把正在录制标识改为false
                            vibrate.recordStatus = false;
                            // 加入一条停止播放的记录
                            vibrate.nowRecords.push({
                                time : stopTime - vibrate.startTime,
                                type : 'stop'                           
                            })
                            
                            // 清空一分钟限制的setTimeout
                            clearTimeout(vibrate.limitTimer)
                            
                            // 提示信息
                            uni.showToast({
                                icon:"success",
                                title:"录制成功!"
                            })                      
                        }
                    }
                })
            }else{
                // 询问是否开始录制
                uni.showModal({
                    title:"提示",
                    content:"确认开始录制吗?",
                    success: (res) => {
                        // 如果点击的是确定
                        if(res.confirm === true){
                            // 提示开始记录
                            uni.showToast({
                                icon:"success",
                                title:"开始录制振动"
                            })
                            // 开始录制
                            vibrate.recordStatus = true;
                            // 清空原本的录制信息
                            // todo:如果有多个录制,那么先把原始录制放到录制列表里面去,并给个名称
                            vibrate.nowRecords = [];
                            // 记录开始录制的时间,后面所有的事件都要减去这个时间,记录相对值
                            vibrate.startTime = new Date().getTime();
                            
                            // 一分钟限制的延时器,即在一分钟后直接执行停止录制操作
                            vibrate.limitTimer = setTimeout(()=>{
                                let stopTime = new Date().getTime();
                                // 此时停止记录
                                vibrate.recordStatus = false;
                                // 并把停止时间放进去
                                vibrate.nowRecords.push({
                                    time : stopTime - vibrate.startTime,
                                    type : 'stop'                           
                                });
                                // 提示一下
                                uni.showToast({
                                    icon:"success",
                                    title:"最长录制一分钟"
                                })
                                console.log("达到一分钟限制")
                            },60*1000)
                        }
                    }
                })
            }
            
        }
    
        // 播放震动
        const onPlayRecord = () => {
            // 如果已经在播放中了,就直接返回了,不执行任何操作
            if(vibrate.isShowing) return ;
            // 如果记录数组的长度是0,说明还没开始录制,给个提示并退出函数
            if(vibrate.nowRecords.length == 0 ) {
                uni.showToast({
                    icon:"error",
                    title:"尚未进行录制"
                })
                return ;
            }
            // 如果当前正在录制中,同样退出函数
            if(vibrate.recordStatus){
                uni.showToast({
                    icon:"error",
                    title:"正在录制中"
                })
                return ;
            }
            // 开始播放
            vibrate.isShowing = true;
            // 循环每一条已经记录好的振动记录
            for(let i = 0; i < vibrate.nowRecords.length; i ++ ){
                // 当前处理的这一条记录
                const item = vibrate.nowRecords[i];
                // 根据记录的相对时间进行延迟操作,这样所有的记录就会按照原来录制的顺序一条一条进行操作了
                // setTimeout(() => {要执行的操作}, 延迟的时间);
                setTimeout(() => {
                    if(item.type == 'short'){
                        // 如果记录的是短振动,执行短振动
                        onShortVibrate();
                    }
                    if(item.type == 'long'){
                        // 如果记录的是长振动,执行长振动
                        onLongVibrate();
                    }
                    // 如果遇到停止标识,或者已经执行到最后一条记录
                    if(item.type == 'stop' || i == vibrate.nowRecords.length - 1){
                        // 提示一下,已经播放完毕
                        uni.showToast({
                            icon:"success",
                            title:"播放完毕!"
                        })
                        // 并恢复正在播放标识
                        vibrate.isShowing = false;
                    }
                },item.time)
            }
        }
        
        // 这里是微信小程序的监听分享的方法,分享的效果在上图
        onShareAppMessage((res) => {        
            return {
                title: "振动录制器", // 分享的名称
                path: "/pages/index/index" // 分享出去的地址
            }
        })
    </script>
    

    <style lang="scss" scoped> 部分

    .content {
            /** 上下左右内边距都为 15rpx */
            padding:15rpx;
            /* 使用flex布局 */
            display: flex;
            /* 布局方向为列方向,即竖着排列 */
            flex-direction: column;
            /* 水平布局为flex的开始位置对齐,即在纵向上从顶部开始布局 */
            justify-content: flex-start;
            /* 在垂直方向上为居中布置,里面的所有元素都会横向(垂直于列,所以是横向)居中 */
            align-items: center;
            /* 定义里面的按钮button元素 */
            button{
                /* 宽度顶满 */
                width:100%;
                /* 上边距20rpx */
                margin-bottom: 20rpx;
                /* 上边距20rpx */
                margin-top: 20rpx;
            }
        }
    
        /* 上面的那个图片 */
        .logo {
            /* 宽高 200rpx */
            height: 200rpx;
            width: 200rpx;
            /* 上外边距 100 */
            margin-top: 100rpx;
        }
    
        /* 图片的动画 */
        .shake {
            /* 动画名称 shake,持续时间 200ms,动画循环无限次 */
            animation: shake 200ms infinite;
        }
        
        /* 关键帧 shake 定义,即动画定义 */
        @keyframes shake {
            /* 10%和90%的时长时 变形往左 4rpx */
            10%,
            90% {
                transform: translateX(-4rpx);
            }
            /* 20%和80%时长时 变形往右 4rpx */
            20%,
            80% {
                transform: translateX(+4rpx);
            }
            /* 变形往左 4rpx */
            30%,
            70% {
                transform: translateX(-4rpx);
            }
            /* 变形往右 4rpx */
            40%,
            60% {
                transform: translateX(+4rpx);
            }
            /* 变形往左 4rpx */
            50% {
                transform: translateX(-4rpx);
            }
        }
    

    调试

    调试时可能会提示安装各种插件,顺序安装即可

    1. 运行 - 运行到内置浏览器,内置H5浏览器无法体验振动以及分享功能
    2. 运行 - 运行到手机或模拟器
    3. 运行 - 运行到小程序模拟器,看到振动及分享功能

    即可体验本次编写的小功能

    总结

    使用到的技术,可以到对应的官方文档中去看看具体用法

    uniapp:onShareAppMessage 分享事件监听、uni.vibrateShort() 短振动、uni.vibrateLong() 长振动

    vue3 : setup 组合式API入口 <script setup> 是一个语法糖、reactive 返回对象的响应式副本、

    css:flex布局、基本盒子模型、@keyframes关键帧定义,scss预编译器

    如果在自己操作过程中有任何的疑问和问题,欢迎交流!

    相关文章

      网友评论

          本文标题:手把手教你实现振动记录器

          本文链接:https://www.haomeiwen.com/subject/vgniortx.html