欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

一、项目概述

运行效果图

image-20260408201635130

image-20260408201649725

image-20260408201655941

1.1 应用简介

触觉翻译是一款创新的感官转换应用,将文字信息转化为触觉震动模式。通过不同的震动编码方式,用户可以"感受"文字的节奏、情感和含义,为视障人士提供辅助,也为普通用户带来全新的信息感知体验。

应用核心理念:让文字可以被触摸,让信息可以被感知。

在数字时代,我们习惯了通过视觉和听觉获取信息,但触觉这一重要感官却常被忽视。触觉翻译打破了传统的信息传递方式,将抽象的文字转化为具体的震动模式,开辟了人机交互的新维度。

1.2 核心功能

功能模块 功能描述 实现方式
文字输入 输入待转换文字 TextField组件
模式选择 选择震动编码模式 枚举类型
强度调节 调整震动强度 四档强度
波形可视化 显示震动波形 CustomPainter
播放控制 播放/停止震动 Timer定时器
历史记录 保存转换历史 本地列表

1.3 震动模式

序号 模式 Emoji 描述 适用场景
1 摩斯密码 📡 文字转摩斯码震动 加密通信、学习摩斯码
2 节奏模式 🎵 根据文字节奏震动 音乐感知、节奏训练
3 情感模式 💭 根据情感强度震动 情感表达、心理应用
4 自定义 ✏️ 用户自定义震动 个性化设置
5 波形模式 🌊 模拟波浪震动 放松冥想、感官体验

1.4 震动强度

强度 Emoji 时长(ms) 描述
轻柔 🌸 100 轻微触感
中等 🌺 200 标准震动
强烈 🌻 400 明显震动
脉冲 💫 150 节奏脉冲

1.5 技术栈

技术领域 技术选型 版本要求
开发框架 Flutter >= 3.0.0
编程语言 Dart >= 2.17.0
设计规范 Material Design 3 -
状态管理 setState -
动画控制 AnimationController -
定时器 Timer -
目标平台 鸿蒙OS / Web API 21+

二、项目结构

lib/
├── main_haptic_translator.dart    # 应用主入口(~850行)
│   ├── HapticTranslatorApp        # 根应用组件
│   ├── HapticMode                 # 震动模式枚举
│   ├── HapticIntensity            # 震动强度枚举
│   ├── HapticPattern              # 震动模式模型
│   ├── HapticUnit                 # 震动单元模型
│   ├── TranslatedHaptic           # 翻译结果模型
│   └── HapticTranslatorHomePage   # 主页面

三、数据模型

3.1 震动模式枚举 (HapticMode)

enum HapticMode {
  morse('摩斯密码', '📡', '将文字转换为摩斯密码震动'),
  rhythm('节奏模式', '🎵', '根据文字节奏震动'),
  emotion('情感模式', '💭', '根据情感强度震动'),
  custom('自定义', '✏️', '自定义震动模式'),
  wave('波形模式', '🌊', '模拟波浪震动');

  final String label;       // 模式名称
  final String icon;        // 代表图标
  final String description; // 模式描述
}

3.2 震动强度枚举 (HapticIntensity)

enum HapticIntensity {
  light('轻柔', '🌸', 100),
  medium('中等', '🌺', 200),
  strong('强烈', '🌻', 400),
  pulse('脉冲', '💫', 150);

  final String label;    // 强度名称
  final String icon;     // 代表图标
  final int duration;    // 震动时长(ms)
}

3.3 震动单元模型 (HapticUnit)

class HapticUnit {
  final int duration;    // 持续时间(ms)
  final bool isVibrate;  // 是否震动
  final int delay;       // 延迟时间(ms)
}

3.4 翻译结果模型 (TranslatedHaptic)

class TranslatedHaptic {
  final String text;              // 原始文字
  final HapticMode mode;          // 震动模式
  final List<HapticUnit> units;   // 震动单元列表
  final int totalDuration;        // 总时长(ms)
  final String visualPattern;     // 可视化模式
}

3.5 数据流转图

输入文字

选择模式

选择强度

转换处理

生成震动单元

计算总时长

可视化显示

播放震动


四、核心功能实现

4.1 摩斯密码转换

摩斯密码是最经典的震动编码方式,将文字转换为点划组合:

List<HapticUnit> _generateMorseUnits(String text) {
  List<HapticUnit> units = [];
  String upperText = text.toUpperCase();

  for (int i = 0; i < upperText.length; i++) {
    String char = upperText[i];
    String? morse = _morseCode[char];

    if (morse != null) {
      for (int j = 0; j < morse.length; j++) {
        if (morse[j] == '.') {
          units.add(HapticUnit(duration: 100, isVibrate: true));  // 短震动
          units.add(HapticUnit(duration: 50, isVibrate: false));  // 短间隔
        } else if (morse[j] == '-') {
          units.add(HapticUnit(duration: 300, isVibrate: true));  // 长震动
          units.add(HapticUnit(duration: 50, isVibrate: false));  // 短间隔
        }
      }
      units.add(HapticUnit(duration: 150, isVibrate: false));     // 字符间隔
    }
  }

  return units;
}

4.2 节奏模式转换

根据字符编码生成不同节奏:

List<HapticUnit> _generateRhythmUnits(String text) {
  List<HapticUnit> units = [];

  for (int i = 0; i < text.length; i++) {
    int charCode = text.codeUnitAt(i);
    int duration = 50 + (charCode % 150);  // 基于字符码计算时长
    int gap = 30 + (charCode % 70);        // 基于字符码计算间隔

    units.add(HapticUnit(duration: duration, isVibrate: true));
    units.add(HapticUnit(duration: gap, isVibrate: false));
  }

  return units;
}

4.3 情感模式转换

根据字符特征生成情感强度震动:

List<HapticUnit> _generateEmotionUnits(String text) {
  List<HapticUnit> units = [];

  for (int i = 0; i < text.length; i++) {
    int intensity = text.codeUnitAt(i) % 4;  // 计算情感强度
    int baseDuration = [80, 150, 250, 400][intensity];

    // 强度越高,震动次数越多
    for (int j = 0; j <= intensity; j++) {
      units.add(HapticUnit(
        duration: baseDuration ~/ (j + 1),
        isVibrate: true,
      ));
      units.add(HapticUnit(duration: 50, isVibrate: false));
    }
    units.add(HapticUnit(duration: 100, isVibrate: false));
  }

  return units;
}

4.4 波形模式转换

使用正弦函数生成波浪形震动:

List<HapticUnit> _generateWaveUnits(String text) {
  List<HapticUnit> units = [];
  int waveLength = text.length;

  for (int i = 0; i < waveLength * 3; i++) {
    double wave = sin(i * 0.5) * 0.5 + 0.5;  // 正弦波
    int duration = (100 + wave * 200).toInt();

    units.add(HapticUnit(duration: duration, isVibrate: true));
    units.add(HapticUnit(duration: 30, isVibrate: false));
  }

  return units;
}

4.5 播放控制

使用Timer实现震动播放:

void _playHaptic() {
  if (_currentTranslation == null || _isPlaying) return;

  setState(() {
    _isPlaying = true;
    _currentUnitIndex = 0;
    _playProgress = 0.0;
  });

  _playNextUnit();
}

void _playNextUnit() {
  if (_currentTranslation == null ||
      _currentUnitIndex >= _currentTranslation!.units.length) {
    setState(() {
      _isPlaying = false;
      _playProgress = 1.0;
    });
    return;
  }

  HapticUnit unit = _currentTranslation!.units[_currentUnitIndex];

  // 触发震动动画
  if (unit.isVibrate) {
    _pulseController.forward().then((_) => _pulseController.reset());
  }

  // 更新进度
  setState(() {
    _playProgress = (_currentUnitIndex + 1) / _currentTranslation!.units.length;
  });

  // 定时播放下一个单元
  _playTimer = Timer(Duration(milliseconds: unit.duration), () {
    setState(() {
      _currentUnitIndex++;
    });
    _playNextUnit();
  });
}

五、UI设计

5.1 色彩系统

应用以紫色为主色调,营造神秘科技感:

颜色类型 色值 用途
背景渐变1 #4A148C 深紫
背景渐变2 #6A1B9A 中紫
背景渐变3 #8E24AA 浅紫
主色调 #9C27B0 紫色
强调色 #BA68C8 浅紫
文字主色 #FFFFFF 白色
文字辅色 #FFFFFF 80% 半透明白

5.2 页面结构

┌─────────────────────────────────────┐
│  📳 触觉翻译                  📳   │  ← 标题栏
│  把文字转换成震动模式               │
├─────────────────────────────────────┤
│  震动模式                           │
│  [📡摩斯] [🎵节奏] [💭情感] ...    │  ← 模式选择
│  ℹ️ 将文字转换为摩斯密码震动        │
├─────────────────────────────────────┤
│  震动强度                           │
│  [🌸轻柔] [🌺中等] [🌻强烈] [💫脉冲]│  ← 强度选择
├─────────────────────────────────────┤
│  ✏️ 输入文字                       │
│  ┌─────────────────────────────┐  │
│  │ 输入要转换的文字...          │  ← 文字输入
│  │                             │  │
│  └─────────────────────────────┘  │
├─────────────────────────────────────┤
│      [ 🔄 转换成震动 ]             │  ← 转换按钮
├─────────────────────────────────────┤
│  震动波形                    5000ms │
│  ┌─────────────────────────────┐  │
│  │ 〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰  │  ← 波形可视化
│  │                             │  │
│  └─────────────────────────────┘  │
│  ████████████░░░░░░░░░░░░░░░░░░░  │  ← 进度条
├─────────────────────────────────────┤
│  [ ▶ 播放震动 ]          [ ⭐ ]   │  ← 播放控制
├─────────────────────────────────────┤
│  📡 震动模式                       │
│  ┌─────────────────────────────┐  │
│  │ "HELLO"                     │  ← 模式显示
│  │ ↓                           │  │
│  │ .... . .-.. .-.. ---        │  │
│  └─────────────────────────────┘  │
│  [震动单元: 25] [静默间隔: 20] ... │
└─────────────────────────────────────┘

5.3 波形可视化

使用CustomPainter绘制震动波形:

class HapticWavePainter extends CustomPainter {
  final List<HapticUnit> units;
  final int currentIndex;
  final bool isPlaying;
  final double progress;

  
  void paint(Canvas canvas, Size size) {
    // 绘制背景
    canvas.drawRect(
      Rect.fromLTWH(0, 0, size.width, size.height),
      bgPaint,
    );

    // 计算总时长
    double totalDuration = units.fold(0, (sum, unit) => sum + unit.duration);

    // 绘制每个震动单元
    for (int i = 0; i < units.length; i++) {
      HapticUnit unit = units[i];
      double width = (unit.duration / totalDuration) * size.width;

      if (unit.isVibrate) {
        // 绘制震动波形(正弦波)
        Path path = Path();
        for (double px = 0; px < width; px += 2) {
          double waveY = y + sin(px * 0.3) * amplitude;
          path.lineTo(x + px, waveY);
        }
        canvas.drawPath(path, paint);
      } else {
        // 绘制静默间隔(直线)
        canvas.drawLine(Offset(x, y), Offset(x + width, y), paint);
      }
    }

    // 绘制播放位置标记
    if (isPlaying) {
      canvas.drawCircle(Offset(progressX, y), 8, markerPaint);
    }
  }
}

5.4 交互设计

交互元素 触发方式 响应行为
模式选择 点击 切换震动模式
强度选择 点击 调整震动强度
转换按钮 点击 生成震动模式
播放按钮 点击 开始/停止播放
历史记录 点击 加载历史转换

六、摩斯密码编码

6.1 字母编码表

字母 摩斯码 震动模式
A .- 短-长
B -… 长-短短短
C -.-. 长-短-长-短
D -… 长-短短
E .
F …-. 短短-长-短
G –. 长长-短
H 短短短短
I 短短
J .— 短-长长长
K -.- 长-短-长
L .-… 短-长-短短
M 长长
N -. 长-短
O 长长长
P .–. 短-长长-短
Q –.- 长长-短-长
R .-. 短-长-短
S 短短短
T -
U …- 短短-长
V …- 短短短-长
W .– 短-长长
X -…- 长-短短-长
Y -.– 长-短-长长
Z –… 长长-短短

6.2 数字编码表

数字 摩斯码 震动模式
0 ----- 五长
1 .---- 短-四长
2 …— 短短-三长
3 …– 短短短-两长
4 …- 短短短短-长
5 五短
6 -… 长-四短
7 –… 两长-三短
8 —… 三长-两短
9 ----. 四长-短

6.3 时长规范

0 ms 30 ms 60 ms 90 ms 120 ms 150 ms 180 ms 210 ms 240 ms 270 ms 300 ms 330 ms 震动 震动 间隔 间隔 间隔 间隔 点(.) 划(-) 字符间 单词间 摩斯密码震动时序

七、状态管理

7.1 状态分类

状态类型 状态名称 说明
输入文字 _textController 文字输入框
震动模式 _selectedMode 当前选择的模式
震动强度 _selectedIntensity 当前选择的强度
翻译结果 _currentTranslation 当前转换结果
播放状态 _isPlaying 是否正在播放
播放进度 _playProgress 播放进度(0-1)
当前单元 _currentUnitIndex 当前播放的单元索引
历史记录 _history 转换历史列表

7.2 状态流转

初始化

输入文字

点击转换

生成结果

点击播放

播放完成

点击停止

清空输入

空闲

输入中

转换中

已转换

播放中

7.3 播放流程图

震动器 Timer 应用 用户 震动器 Timer 应用 用户 alt [是震动单元] loop [每个震动单元] 点击播放 重置状态 创建定时器 触发回调 更新进度 触发震动动画 延迟duration毫秒 播放完成 更新UI状态

八、震动波形可视化

8.1 波形绘制原理

震动波形的可视化采用正弦波模拟:

y(t)=A⋅sin⁡(ωt+ϕ)y(t) = A \cdot \sin(\omega t + \phi)y(t)=Asin(ωt+ϕ)

其中:

  • AAA 为振幅,表示震动的"强度"
  • ω\omegaω 为角频率,控制波形的疏密
  • ϕ\phiϕ 为初相位,控制波形的起始位置

8.2 波形类型

模式 波形特征 数学表达
摩斯密码 方波脉冲 f(t)=sgn(sin⁡(t))f(t) = \text{sgn}(\sin(t))f(t)=sgn(sin(t))
节奏模式 变频脉冲 f(t)=sin⁡(ω(t)⋅t)f(t) = \sin(\omega(t) \cdot t)f(t)=sin(ω(t)t)
情感模式 衰减脉冲 f(t)=A⋅e−λt⋅sin⁡(t)f(t) = A \cdot e^{-\lambda t} \cdot \sin(t)f(t)=Aeλtsin(t)
波形模式 正弦波 f(t)=A⋅sin⁡(t)f(t) = A \cdot \sin(t)f(t)=Asin(t)
自定义 混合波 f(t)=∑Ai⋅sin⁡(ωit)f(t) = \sum A_i \cdot \sin(\omega_i t)f(t)=Aisin(ωit)

8.3 可视化效果

震动单元: ████████░░░████████████░░░██████░░░████████
          └──震动──┘间隔└──震动──┘间隔└震动┘间隔└──震动──

波形显示:  〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰
           /\  /\      /\    /\  /\
          /  \/  \____/  \__/  \/  \____

九、应用场景

9.1 辅助功能

辅助功能

视障人士

文字感知

导航提示

信息获取

听障人士

通知提醒

消息提示

警报信号

老年用户

大字体配合

简化操作

触觉反馈

9.2 娱乐应用

场景 描述 震动模式
情感表达 发送"心跳"给朋友 情感模式
秘密通信 摩斯密码传递信息 摩斯模式
游戏互动 震动谜题解密 自定义模式
冥想放松 波浪震动放松 波形模式

9.3 教育应用

场景 描述 效果
摩斯码学习 通过震动学习摩斯码 肌肉记忆
节奏训练 感受不同文字的节奏 节奏感知
语言学习 触觉辅助记忆 多感官学习

十、性能优化

10.1 渲染优化

优化点 实现方式 效果
波形绘制 CustomPainter 高效绘制
进度更新 setState局部 减少重绘
动画控制 AnimationController 流畅动画
定时器 Timer精准控制 准确播放

10.2 内存管理


void dispose() {
  _textController.dispose();
  _waveController.dispose();
  _pulseController.dispose();
  _playTimer?.cancel();  // 取消定时器
  super.dispose();
}

10.3 性能指标

指标 目标值 实测值
波形绘制 60fps 60fps
播放延迟 < 10ms 待测试
内存占用 < 30MB 待测试
CPU占用 < 10% 待测试

十一、常见问题

11.1 问题排查

问题 原因 解决方案
震动不工作 设备不支持 检查设备能力
波形不显示 units为空 检查转换逻辑
播放卡顿 Timer冲突 取消旧Timer
进度不准 计算错误 检查总时长

11.2 调试技巧

// 打印震动单元
debugPrint('Total units: ${units.length}');
debugPrint('Vibrate units: ${units.where((u) => u.isVibrate).length}');
debugPrint('Total duration: ${units.fold(0, (sum, u) => sum + u.duration)}ms');

// 打印播放状态
debugPrint('Playing: $_isPlaying');
debugPrint('Progress: $_playProgress');
debugPrint('Current unit: $_currentUnitIndex');

十二、运行说明

12.1 环境要求

环境 版本要求
Flutter SDK >= 3.0.0
Dart SDK >= 2.17.0
鸿蒙OS API 21+

12.2 运行命令

# 查看可用设备
flutter devices

# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_haptic_translator.dart

# 运行到Web服务器
flutter run -d web-server -t lib/main_haptic_translator.dart --web-port 8130

# 运行到Windows
flutter run -d windows -t lib/main_haptic_translator.dart

# 代码分析
flutter analyze lib/main_haptic_translator.dart

十三、扩展建议

13.1 功能扩展

功能 优先级 实现思路
真实震动 集成vibration包
音频配合 播放对应音效
分享功能 导出震动模式
录制震动 自定义录制
云端同步 账号系统

13.2 设计扩展

方向 描述
主题切换 多种配色主题
波形样式 不同波形样式
动画效果 更丰富的动画
音效反馈 操作音效

13.3 技术扩展

2024-01-07 2024-01-14 2024-01-21 2024-01-28 2024-02-04 2024-02-11 2024-02-18 2024-02-25 2024-03-03 2024-03-10 2024-03-17 2024-03-24 模式转换 波形可视化 播放控制 真实震动 音频配合 分享功能 云端同步 社区分享 高级模式 V1.0 基础版本 V1.1 增强版本 V1.2 社交版本 触觉翻译应用开发计划

十四、无障碍设计

14.1 设计原则

无障碍设计

可感知性

触觉反馈

视觉辅助

多模态输出

可操作性

大按钮

简单手势

语音控制

可理解性

清晰提示

一致性

错误预防

健壮性

兼容性

稳定性

容错性

14.2 辅助功能清单

功能 实现状态 描述
大字体支持 系统字体缩放
高对比度 深色主题
触觉反馈 核心功能
语义标签 待实现
语音播报 待实现

十五、总结

触觉翻译应用通过创新的"触觉编码"概念,将文字信息转化为可感知的震动模式。应用核心亮点包括:

15.1 核心特色

  1. 多种模式:5种震动编码模式,满足不同需求
  2. 强度可调:4档震动强度,适应不同场景
  3. 可视化:实时显示震动波形
  4. 播放控制:精准的震动播放控制
  5. 历史记录:保存常用转换

15.2 技术亮点

  • 枚举类型设计:模式、强度使用枚举,代码清晰
  • CustomPainter:高效绘制震动波形
  • Timer控制:精准的震动时序控制
  • AnimationController:流畅的动画效果
  • 状态管理:清晰的播放状态流转

15.3 应用价值

触觉翻译不仅是一个有趣的工具,更是一个具有实际应用价值的产品。它为视障人士提供了新的信息获取方式,为普通用户带来了全新的感官体验,也为触觉交互领域提供了创新思路。

让文字可以被触摸,让信息可以被感知!


愿每一次震动都能传递有意义的信息 📳

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐