• 【HarmonyOS】应用振动效果实现


    一、问题背景:
    应用在强提醒场景下,一般会有马达振动的效果,提示用户注意力的关注。

    比如消息提醒,扫码提示,删除键确认提示等。

    针对高定制化或者固定的振动方式,我们需要有不同的方案实现,马达振动效果。

    二、解决方案:
    鸿蒙针对振动效果的实现,有多种方案,目前分为振动和音振协同两种方式。

    单纯的只是振动,又分为三种方式:

    1. 系统定制的振动方式,例如闹钟
    2. 非系统定制,自定义振动配置json文件的方式
    3. 线性马达振动,只需要设置时间和强度(最简单的调用方式)

    音振协同一般用于,音效播放和振动同时的场景,例如扫码。

    1.首先需要配置振动权限,该权限是系统权限,只需要配置后,默认就会被授权。
    ohos.permission.VIBRATE

    2.之后根据需要实现不同的马达振动效果,方案调用详情参见下方代码示例的注释。

    三、DEMO示例:

    import vibrator from '@ohos.vibrator';
    import { BusinessError } from '@ohos.base';
    import { resourceManager } from '@kit.LocalizationKit';
    
    /**
     * 振动管理类
     * 需要权限: ohos.permission.VIBRATE
     */
    export class HapticMgr {
      private TAG: string = 'HapticMgr';
    
      private static mHapticMgr: HapticMgr | undefined = undefined;
    
      public static Ins(): HapticMgr{
        if(!HapticMgr.mHapticMgr){
          HapticMgr.mHapticMgr = new HapticMgr();
        }
        return HapticMgr.mHapticMgr;
      }
    
      /**
       * 按照指定持续时间触发马达振动
       */
      public timeVibration(){
        try {
          // 触发马达振动
          vibrator.startVibration({
            type: 'time',
            duration: 1000,
          }, {
            id: 0,
            usage: 'alarm'
          }, (error: BusinessError) => {
            if (error) {
              console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`);
              return;
            }
            console.info('Succeed in starting vibration');
          });
        } catch (err) {
          let e: BusinessError = err as BusinessError;
          console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
        }
      }
    
      /**
       * 按照预置振动效果触发马达振动,可先查询振动效果是否被支持,再调用振动接口
       */
      public typeVibration(){
    
        try {
          // 查询是否支持'haptic.clock.timer'
          vibrator.isSupportEffect('haptic.clock.timer', (err: BusinessError, state: boolean) => {
            if (err) {
              console.error(`Failed to query effect. Code: ${err.code}, message: ${err.message}`);
              return;
            }
            console.info('Succeed in querying effect');
            if (state) {
              try {
                // 触发马达振动
                vibrator.startVibration({
                  type: 'preset',
                  effectId: 'haptic.clock.timer',
                  count: 1,
                }, {
                  usage: 'unknown'
                }, (error: BusinessError) => {
                  if (error) {
                    console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`);
                  } else {
                    console.info('Succeed in starting vibration');
                  }
                });
              } catch (error) {
                let e: BusinessError = error as BusinessError;
                console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
              }
            }
          })
        } catch (error) {
          let e: BusinessError = error as BusinessError;
          console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
        }
      }
    
      public fileVibration(){
        const fileName: string = 'vibration.json';
    
        // 获取文件资源描述符
        let rawFd: resourceManager.RawFileDescriptor = getContext().resourceManager.getRawFdSync(fileName);
    
        // 触发马达振动
        try {
          vibrator.startVibration({
            type: "file",
            hapticFd: { fd: rawFd.fd, offset: rawFd.offset, length: rawFd.length }
          }, {
            id: 0,
            usage: 'alarm'
          }, (error: BusinessError) => {
            if (error) {
              console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`);
              return;
            }
            console.info('Succeed in starting vibration');
          });
        } catch (err) {
          let e: BusinessError = err as BusinessError;
          console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
        }
    
        // 关闭文件资源描述符
        getContext().resourceManager.closeRawFdSync(fileName);
      }
    
      /**
       * 按照指定模式停止对应的马达振动,自定义振动不支持此类停止方式
       */
      public stopVibrationByType(){
        //  停止固定时长振动
        try {
          // 按照VIBRATOR_STOP_MODE_TIME模式停止振动
          vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_TIME, (error: BusinessError) => {
            if (error) {
              console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`);
              return;
            }
            console.info('Succeed in stopping vibration');
          })
        } catch (err) {
          let e: BusinessError = err as BusinessError;
          console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
        }
    
        // 停止预置振动:
        try {
          // 按照VIBRATOR_STOP_MODE_PRESET模式停止振动
          vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_PRESET, (error: BusinessError) => {
            if (error) {
              console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`);
              return;
            }
            console.info('Succeed in stopping vibration');
          })
        } catch (err) {
          let e: BusinessError = err as BusinessError;
          console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
        }
    
      }
    
      /**
       * 停止所有模式的马达振动,包括自定义振动:
       */
      public stopVibration(){
        try {
          // 停止所有模式的马达振动
          vibrator.stopVibration((error: BusinessError) => {
            if (error) {
              console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`);
              return;
            }
            console.info('Succeed in stopping vibration');
          })
        } catch (error) {
          let e: BusinessError = error as BusinessError;
          console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
        }
      }
    
    
    }
    

    振动配置文件:
    在这里插入图片描述

    {
      "MetaData": {
        "Create": "2023-01-09",
        "Description": "a haptic case",
        "Version": 1.0,
        "ChannelNumber": 1
      },
      "Channels": [
        {
          "Parameters": {
            "Index": 0
          },
          "Pattern": [
            {
              "Event": {
                "Type": "transient",
                "StartTime": 0,
                "Parameters": {
                  "Frequency": 31,
                  "Intensity": 100
                }
              }
            },
            {
              "Event": {
                "Type": "continuous",
                "StartTime": 40,
                "Duration": 54,
                "Parameters": {
                  "Frequency": 30,
                  "Intensity": 38,
                  "Curve": [
                    {
                      "Time": 0,
                      "Frequency": 0,
                      "Intensity": 0
                    },
                    {
                      "Time": 1,
                      "Frequency": 15,
                      "Intensity": 0.5
                    },
                    {
                      "Time": 40,
                      "Frequency": -8,
                      "Intensity": 1.0
                    },
                    {
                      "Time": 54,
                      "Frequency": 0,
                      "Intensity": 0
                    }
                  ]
                }
              }
            }
          ]
        }
      ]
    }
    
  • 相关阅读:
    关于python的odl库的相关问题解决
    linux驱动 设备驱动模型
    Python基础dict字典定义与函数
    SAGAN
    mysql的DDL语言和DML语言
    CS学习记录-探测_提取配置
    【李航统计学习笔记】第九章:EM算法
    java计算机毕业设计基于springboot电商项目(附源码讲解)
    VMware vCenter 从6.7跨版本升级至7.0U3N
    企业开发项目完整流程
  • 原文地址:https://blog.csdn.net/u010949451/article/details/139450935