焦虑粉碎机应用


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

一、项目概述

运行效果图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.1 应用简介

焦虑粉碎机是一款帮助用户释放心理压力的情绪管理应用。用户可以将内心的烦恼、焦虑写下来,通过"粉碎"动画效果,象征性地将负面情绪消除,达到心理疏导的目的。

应用采用"输入-粉碎-记录"的闭环设计,让用户在写下烦恼的过程中梳理情绪,在粉碎动画中获得释放感,在历史记录中回顾自己的成长轨迹。

1.2 核心功能

功能模块 功能描述 实现方式
烦恼输入 多行文本输入、字数限制 TextField、maxLength
粉碎动画 震动效果 + 粒子飞散 AnimationController、CustomPainter
历史记录 分类展示、状态管理 SliverList、状态筛选
记录管理 粉碎、删除操作 状态更新、列表操作
统计展示 待粉碎/已粉碎数量 实时统计卡片

1.3 粉碎动画流程

阶段 时长 效果描述
1 500ms 输入框快速震动,模拟蓄力
2 1500ms 50个彩色粒子飞散,模拟粉碎
3 即时 记录状态更新,显示完成提示

1.4 技术栈

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

二、项目结构

lib/
├── main_anxiety_crusher.dart    # 应用主入口(712行)
│   ├── AnxietyCrusherApp        # 根应用组件
│   ├── AnxietyRecord            # 数据模型
│   ├── AnxietyCrusherHomePage   # 主页面
│   ├── Particle                 # 粒子模型
│   └── ParticlePainter          # 粒子绘制器

三、数据模型

3.1 AnxietyRecord 模型

class AnxietyRecord {
  final String id;              // 唯一标识(时间戳)
  final String content;         // 烦恼内容
  final DateTime createdAt;     // 创建时间
  DateTime? crushedAt;          // 粉碎时间
  bool isCrushed;               // 是否已粉碎

  AnxietyRecord({
    required this.id,
    required this.content,
    required this.createdAt,
    this.crushedAt,
    this.isCrushed = false,
  });
}

3.2 Particle 模型

class Particle {
  double x;                     // X坐标
  double y;                     // Y坐标
  double vx;                    // X轴速度
  double vy;                    // Y轴速度
  double size;                  // 粒子大小
  Color color;                  // 粒子颜色
  double rotation;              // 旋转角度
  double rotationSpeed;         // 旋转速度
  double opacity = 1.0;         // 透明度

  void update() {
    x += vx;
    y += vy;
    vy += 0.3;                  // 重力加速度
    rotation += rotationSpeed;
    opacity -= 0.015;           // 渐隐效果
  }
}

四、核心功能实现

4.1 粉碎动画实现

粉碎动画由三个阶段组成:震动、粒子生成、飞散动画。

void _startCrushAnimation() async {
  setState(() => _isCrushing = true);

  // 阶段1:震动效果
  for (int i = 0; i < 5; i++) {
    await _shakeController.forward(from: 0);
    await Future.delayed(const Duration(milliseconds: 50));
  }

  // 阶段2:生成粒子
  _generateParticles();

  // 阶段3:粒子飞散动画
  await _particleController.forward(from: 0);

  // 更新记录状态
  setState(() {
    _currentRecord!.isCrushed = true;
    _currentRecord!.crushedAt = DateTime.now();
    _isCrushing = false;
    _particles.clear();
  });
}

4.2 粒子生成算法

生成50个随机属性的粒子,确保视觉效果丰富:

void _generateParticles() {
  _particles.clear();
  final random = Random();

  for (int i = 0; i < 50; i++) {
    _particles.add(Particle(
      x: 0,
      y: 0,
      vx: (random.nextDouble() - 0.5) * 15,  // 随机水平速度
      vy: (random.nextDouble() - 0.5) * 15 - 5,  // 随机垂直速度(向上偏移)
      size: random.nextDouble() * 8 + 4,     // 随机大小 4-12
      color: [                               // 随机颜色
        const Color(0xFF6C5CE7),
        const Color(0xFF00B894),
        const Color(0xFFFDCB6E),
        const Color(0xFFE17055),
        const Color(0xFF74B9FF),
      ][random.nextInt(5)],
      rotation: random.nextDouble() * 2 * pi,
      rotationSpeed: (random.nextDouble() - 0.5) * 0.3,
    ));
  }
}

4.3 粒子绘制器

使用 CustomPainter 实现高性能粒子渲染:

class ParticlePainter extends CustomPainter {
  final List<Particle> particles;
  final double progress;

  
  void paint(Canvas canvas, Size size) {
    final centerX = size.width / 2;
    final centerY = size.height / 2;

    for (var particle in particles) {
      if (particle.opacity <= 0) continue;

      final paint = Paint()
        ..color = particle.color.withValues(alpha: particle.opacity)
        ..style = PaintingStyle.fill;

      canvas.save();
      canvas.translate(centerX + particle.x, centerY + particle.y);
      canvas.rotate(particle.rotation);

      // 绘制不规则碎片形状
      final path = Path();
      path.moveTo(-particle.size / 2, -particle.size / 2);
      path.lineTo(particle.size / 2, -particle.size / 3);
      path.lineTo(particle.size / 3, particle.size / 2);
      path.lineTo(-particle.size / 3, particle.size / 3);
      path.close();

      canvas.drawPath(path, paint);
      canvas.restore();
    }
  }

  
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

五、UI设计

5.1 色彩系统

用途 色值 说明
主色调 #6C5CE7 紫色,代表平静与治愈
辅助色1 #00B894 绿色,代表已粉碎状态
辅助色2 #FDCB6E 黄色,代表待处理状态
辅助色3 #E17055 橙色,用于粒子效果
辅助色4 #74B9FF 蓝色,用于粒子效果
背景渐变起始 #6C5CE7 头部渐变
背景渐变结束 #8B7FD4 头部渐变

5.2 页面结构

┌─────────────────────────────────┐
│  🔮 焦虑粉碎机                   │  ← 渐变头部
│  写下烦恼,一键粉碎              │
│  ┌─────────┐ ┌─────────┐        │
│  │待粉碎 3 │ │已粉碎 5 │        │  ← 统计卡片
│  └─────────┘ └─────────┘        │
├─────────────────────────────────┤
│  写下你的烦恼                    │
│  ┌─────────────────────────┐   │
│  │ 工作压力太大了...       │   │  ← 输入框
│  │                          │   │
│  └─────────────────────────┘   │
│  ┌─────────────────────────┐   │
│  │ ⚡ 立即粉碎             │   │  ← 粉碎按钮
│  └─────────────────────────┘   │
├─────────────────────────────────┤
│  ▼ 待粉碎的烦恼                 │
│  ┌─────────────────────────┐   │
│  │ ⏳ 待粉碎  今天 14:30  ⚡🗑️│   │  ← 烦恼卡片
│  │ 工作压力太大了...        │   │
│  └─────────────────────────┘   │
├─────────────────────────────────┤
│  ▼ 已粉碎的烦恼                 │
│  ┌─────────────────────────┐   │
│  │ ✓ 已粉碎  今天 14:25  🗑️│   │  ← 已粉碎(删除线)
│  │ ~~考试好紧张~~           │   │
│  └─────────────────────────┘   │
└─────────────────────────────────┘

5.3 交互设计

交互元素 触发方式 响应行为
输入框 点击 获取焦点,可输入文字
立即粉碎按钮 点击 触发粉碎动画,清空输入框
烦恼卡片-粉碎按钮 点击 对该记录触发粉碎动画
烦恼卡片-删除按钮 点击 删除该记录
空状态 无记录时显示 提示用户写下烦恼

六、动画详解

6.1 震动动画

使用正弦函数实现左右震动效果:

AnimatedBuilder(
  animation: _shakeController,
  builder: (context, child) {
    final shake = sin(_shakeController.value * pi * 10) * 5;
    return Transform.translate(
      offset: Offset(shake, 0),
      child: Container(...),
    );
  },
)

参数说明:

  • pi * 10:震动频率,数值越大震动越快
  • * 5:震动幅度,单位是像素
  • 循环5次,每次100ms

6.2 粒子动画

粒子动画基于物理模拟:

物理属性 计算方式 效果
位置更新 x += vx, y += vy 匀速运动
重力模拟 vy += 0.3 向下加速
旋转 rotation += rotationSpeed 自转效果
渐隐 opacity -= 0.015 逐渐消失

6.3 动画时序

震动阶段 0ms 开始震动 100ms 第1次震动 200ms 第2次震动 300ms 第3次震动 400ms 第4次震动 500ms 第5次震动结束 粒子阶段 500ms 生成50个粒子 1000ms 粒子飞散中 1500ms 粒子渐隐 2000ms 动画结束 粉碎动画时序图

七、状态管理

7.1 状态分类

状态类型 状态名称 说明
输入状态 _textController 输入框文本
动画状态 _isCrushing 是否正在粉碎
粒子状态 _particles 当前粒子列表
记录状态 _records 所有烦恼记录
当前记录 _currentRecord 正在粉碎的记录

7.2 状态流转

打开应用

点击粉碎按钮

动画完成

继续输入

添加记录

点击粉碎

点击删除

点击删除

输入中

粉碎中

已粉碎

待粉碎

已删除


八、性能优化

8.1 渲染优化

优化点 实现方式 效果
粒子复用 使用对象池(可扩展) 减少内存分配
脏区域渲染 CustomPainter精准重绘 只重绘动画区域
列表懒加载 SliverList 只渲染可见项

8.2 内存管理


void dispose() {
  _textController.dispose();
  _shakeController.dispose();
  _particleController.dispose();
  _scaleController.dispose();
  super.dispose();
}

8.3 性能指标

指标 目标值 实测值
动画帧率 60fps 60fps
内存占用 < 50MB 待测试
启动时间 < 2s 待测试

九、常见问题

9.1 问题排查

问题 原因 解决方案
粒子不显示 AnimationController未启动 检查forward()调用
震动效果不明显 震动幅度太小 调整震动参数
记录状态不更新 未调用setState 确保状态更新后调用setState
历史记录丢失 内存存储重启清空 迁移至持久化存储

9.2 调试技巧

// 打印粒子数量
debugPrint('Particles: ${_particles.length}');

// 检查动画状态
debugPrint('IsCrushing: $_isCrushing');
debugPrint('Animation Value: ${_particleController.value}');

// 检查记录状态
for (var record in _records) {
  debugPrint('Record: ${record.content}, Crushed: ${record.isCrushed}');
}

十、运行说明

10.1 环境要求

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

10.2 运行命令

# 查看可用设备
flutter devices

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

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

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

十一、扩展建议

11.1 功能扩展

功能 优先级 实现思路
数据持久化 使用SharedPreferences或SQLite
粉碎音效 集成audioplayers播放音效
震动反馈 使用HapticFeedback
分享功能 使用share_plus
数据统计 记录粉碎次数、时间分布

11.2 设计扩展

方向 描述
主题切换 支持多种粉碎主题(火焰、雪花、星星等)
粒子定制 允许用户选择粒子颜色和形状
成就系统 粉碎一定数量解锁成就徽章

十二、总结

焦虑粉碎机应用通过直观的"写下-粉碎"交互模式,帮助用户释放心理压力。应用核心亮点包括:

  1. 沉浸式动画:50个粒子飞散效果,视觉冲击力强
  2. 流畅交互:震动+粒子双重反馈,操作感好
  3. 状态管理:清晰的待粉碎/已粉碎分类
  4. 简洁设计:Material Design 3,界面清爽

应用代码结构清晰,共712行,无第三方依赖,易于理解和维护。后续可扩展数据持久化、音效反馈等功能,提升用户体验。

粉碎焦虑,释放压力!

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐