风的方向应用


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

一、项目概述

运行效果图

image-20260408180657943

image-20260408180708039

1.1 应用简介

风的方向是一款充满诗意的自然主题应用,通过追踪风的方向和速度,让用户感受自然的流动与韵律。应用以蓝色为主色调,象征着天空与海洋,配合动态粒子效果和风向罗盘,为用户带来沉浸式的自然体验。

应用核心理念:听风的声音,感受自然的呼吸。

风,是自然的信使,是季节的语言。它从北方的冰雪中带来寒冷,从南方的海洋里带来温暖,从东方的森林中带来湿润,从西方的沙漠里带来干燥。每一阵风都有它的故事,每一缕风都有它的方向。本应用通过科技的方式,让我们重新认识这位自然的朋友。

1.2 核心功能

功能模块 功能描述 实现方式
风向罗盘 可视化风向显示 CustomPainter绘制
风速显示 八级风速等级 枚举分类
粒子效果 风流动画效果 粒子系统
风向历史 24小时风向变化 折线图
天气信息 温度湿度显示 模拟数据
风之诗 根据风速生成诗句 文字映射

1.3 风向定义

序号 风向 Emoji 角度 描述
1 北风 ⬆️ 来自北方的寒风
2 东北风 ↗️ 45° 东北方向的微风
3 东风 ➡️ 90° 东方吹来的湿润之风
4 东南风 ↘️ 135° 东南方向的暖风
5 南风 ⬇️ 180° 来自南方的温暖之风
6 西南风 ↙️ 225° 西南方向的柔风
7 西风 ⬅️ 270° 西方吹来的干燥之风
8 西北风 ↖️ 315° 西北方向的冷风

1.4 风速等级

等级 名称 Emoji 风速范围 描述
0 无风 🍃 0-0.2 m/s 树叶静止,炊烟直上
1 微风 🌿 0.3-1.5 m/s 树叶微动,轻拂面颊
2 轻风 🌱 1.6-3.3 m/s 树叶摇动,旗帜飘扬
3 和风 🌾 3.4-5.4 m/s 小枝摇动,灰尘飞扬
4 清风 🌴 5.5-7.9 m/s 小树摇摆,水波荡漾
5 强风 🌳 8.0-10.7 m/s 大树摇动,举伞困难
6 疾风 🌲 10.8-13.8 m/s 树枝折断,行走困难
7 大风 🏔️ 13.9-17.1 m/s 树木连根拔起

1.5 技术栈

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

二、项目结构

lib/
├── main_wind_direction.dart    # 应用主入口(~750行)
│   ├── WindDirectionApp        # 根应用组件
│   ├── WindDirection           # 风向枚举
│   ├── WindSpeed               # 风速枚举
│   ├── WindData                # 风数据模型
│   ├── WindParticle            # 粒子模型
│   ├── WindDirectionHomePage   # 主页面
│   ├── ArrowPainter            # 箭头绘制器
│   ├── ParticlePainter         # 粒子绘制器
│   └── WindHistoryPainter      # 历史绘制器

三、数据模型

3.1 风向枚举 (WindDirection)

enum WindDirection {
  north('北风', '⬆️', 0, '来自北方的寒风'),
  northEast('东北风', '↗️', 45, '东北方向的微风'),
  east('东风', '➡️', 90, '东方吹来的湿润之风'),
  southEast('东南风', '↘️', 135, '东南方向的暖风'),
  south('南风', '⬇️', 180, '来自南方的温暖之风'),
  southWest('西南风', '↙️', 225, '西南方向的柔风'),
  west('西风', '⬅️', 270, '西方吹来的干燥之风'),
  northWest('西北风', '↖️', 315, '西北方向的冷风');

  final String label;       // 风向名称
  final String icon;        // 代表图标
  final int degree;         // 角度
  final String description; // 描述

  // 从角度计算风向
  static WindDirection fromDegree(int degree) {
    final normalizedDegree = ((degree % 360) + 360) % 360;
    final index = ((normalizedDegree + 22.5) ~/ 45) % 8;
    return WindDirection.values[index];
  }
}

3.2 风速枚举 (WindSpeed)

enum WindSpeed {
  calm('无风', '🍃', 0, 0.2, '树叶静止,炊烟直上'),
  light('微风', '🌿', 0.3, 1.5, '树叶微动,轻拂面颊'),
  gentle('轻风', '🌱', 1.6, 3.3, '树叶摇动,旗帜飘扬'),
  moderate('和风', '🌾', 3.4, 5.4, '小枝摇动,灰尘飞扬'),
  fresh('清风', '🌴', 5.5, 7.9, '小树摇摆,水波荡漾'),
  strong('强风', '🌳', 8.0, 10.7, '大树摇动,举伞困难'),
  gale('疾风', '🌲', 10.8, 13.8, '树枝折断,行走困难'),
  storm('大风', '🏔️', 13.9, 17.1, '树木连根拔起');

  final String label;       // 等级名称
  final String icon;        // 代表图标
  final double minSpeed;    // 最小风速
  final double maxSpeed;    // 最大风速
  final String description; // 描述

  // 从风速值计算等级
  static WindSpeed fromSpeed(double speed) {
    for (var ws in WindSpeed.values) {
      if (speed >= ws.minSpeed && speed <= ws.maxSpeed) {
        return ws;
      }
    }
    return WindSpeed.storm;
  }
}

3.3 风数据模型 (WindData)

class WindData {
  final WindDirection direction;  // 风向
  final WindSpeed speed;          // 风速等级
  final double speedValue;        // 风速值(m/s)
  final DateTime timestamp;       // 时间戳
  final double temperature;       // 温度
  final int humidity;             // 湿度
}

3.4 粒子模型 (WindParticle)

class WindParticle {
  double x;        // X坐标(0.0-1.0)
  double y;        // Y坐标(0.0-1.0)
  double speed;    // 移动速度
  double size;     // 粒子大小
  double opacity;  // 透明度
  double angle;    // 角度
}

3.5 数据流转图

随机生成

WindData

风向计算

风速计算

罗盘显示

粒子动画

历史记录

折线图

风之诗


四、核心功能实现

4.1 风向计算

从角度计算风向的算法:

static WindDirection fromDegree(int degree) {
  // 规范化角度到0-360度
  final normalizedDegree = ((degree % 360) + 360) % 360;
  
  // 计算风向索引(每个风向占45度)
  final index = ((normalizedDegree + 22.5) ~/ 45) % 8;
  
  return WindDirection.values[index];
}

计算原理:

index=⌊degree+22.545⌋mod  8 index = \lfloor \frac{degree + 22.5}{45} \rfloor \mod 8 index=45degree+22.5mod8

其中:

  • degreedegreedegree 为原始角度(0-360°)
  • 22.522.522.5 为偏移量,确保边界正确
  • 454545 为每个风向的角度范围
  • 888 为风向总数

4.2 风速等级判断

static WindSpeed fromSpeed(double speed) {
  for (var ws in WindSpeed.values) {
    if (speed >= ws.minSpeed && speed <= ws.maxSpeed) {
      return ws;
    }
  }
  return WindSpeed.storm;
}

4.3 风数据生成

WindData _generateWindData({DateTime? timestamp}) {
  final degree = _random.nextInt(360);
  final speed = _random.nextDouble() * 15;
  final direction = WindDirection.fromDegree(degree);
  final windSpeed = WindSpeed.fromSpeed(speed);

  return WindData(
    direction: direction,
    speed: windSpeed,
    speedValue: speed,
    timestamp: timestamp ?? DateTime.now(),
    temperature: 15 + _random.nextDouble() * 20,
    humidity: 40 + _random.nextInt(40),
  );
}

4.4 粒子系统更新

void _updateParticles() {
  if (_currentWind == null) return;

  final windAngle = _currentWind!.direction.degree * pi / 180;

  for (var particle in _particles) {
    // 根据风向和风速更新粒子位置
    particle.x += cos(windAngle) * particle.speed * (_currentWind!.speedValue / 5);
    particle.y += sin(windAngle) * particle.speed * (_currentWind!.speedValue / 5);

    // 边界检测和重生
    if (particle.x < 0 || particle.x > 1 || particle.y < 0 || particle.y > 1) {
      particle.x = _random.nextDouble();
      particle.y = _random.nextDouble();
      particle.opacity = 0.3 + _random.nextDouble() * 0.5;
    }
  }

  setState(() {});
}

4.5 罗盘箭头绘制

class ArrowPainter extends CustomPainter {
  final Color color;

  
  void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2, size.height / 2);
    final paint = Paint()
      ..color = color
      ..style = PaintingStyle.fill;

    // 绘制箭头路径
    final path = Path();
    path.moveTo(center.dx, center.dy - 70);
    path.lineTo(center.dx - 15, center.dy + 20);
    path.lineTo(center.dx, center.dy + 10);
    path.lineTo(center.dx + 15, center.dy + 20);
    path.close();

    canvas.drawPath(path, paint);

    // 添加发光效果
    final shadowPaint = Paint()
      ..color = color.withValues(alpha: 0.3)
      ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 10);
    canvas.drawPath(path, shadowPaint);
  }
}

五、UI设计

5.1 色彩系统

应用以蓝色为主色调,象征天空与海洋:

颜色类型 色值 用途
背景渐变1 #1A237E 深蓝
背景渐变2 #0277BD 中蓝
背景渐变3 #00BCD4 青色
主色调 #00BCD4 青色
罗盘颜色 #B2EBF2 浅青
文字主色 #FFFFFF 白色
文字辅色 #FFFFFF 80% 半透明白

5.2 页面结构

┌─────────────────────────────────────┐
│  🌬️ 风的方向        🌡️25° 💧65%   │  ← 标题栏
│  追踪风的方向,感受自然的流动        │
├─────────────────────────────────────┤
│                                     │
│           N                        │
│         ╱   ╲                      │
│       W ───── E                   │  ← 风向罗盘
│         ╲   ╱                      │
│           S                        │
│           ↗️                       │
│          东北风                     │
│          3.5 m/s                   │
│                                     │
├─────────────────────────────────────┤
│  ↗️东北风  🌾和风  3.5m/s         │  ← 风速信息
│  ℹ️ 小枝摇动,灰尘飞扬              │
├─────────────────────────────────────┤
│                                     │
│  ·  ·  ·  ·  ·  ·  ·  ·           │  ← 粒子效果
│    ·  ·  ·  ·  ·  ·  ·            │
│  ·  ·  ·  ·  ·  ·  ·  ·           │
│                                     │
├─────────────────────────────────────┤
│  风向变化           最近24小时      │
│  ∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿∿            │  ← 历史曲线
│                                     │
├─────────────────────────────────────┤
│  📖 风之诗                          │
│                                     │
│  轻风过林梢                         │  ← 诗句展示
│  枝叶舞翩跹                         │
│  鸟鸣声声脆                         │
│  心随自然闲                         │
└─────────────────────────────────────┘

5.3 罗盘设计

5.3.1 罗盘结构
        N (0°)
        ↑
        │
W ←─────┼─────→ E (90°)
(270°)  │      (90°)
        ↓
        S (180°)
5.3.2 风向角度映射
13% 13% 13% 13% 13% 13% 13% 13% 风向角度分布 北风 0° 东北风 45° 东风 90° 东南风 135° 南风 180° 西南风 225° 西风 270° 西北风 315°

5.4 交互设计

交互元素 触发方式 响应行为
罗盘箭头 自动 根据风向旋转
粒子动画 自动 随风向流动
风数据 每5秒 自动更新
历史曲线 自动 实时绘制

六、动画详解

6.1 动画控制器

应用使用三个动画控制器:

// 罗盘旋转动画
_compassController = AnimationController(
  vsync: this,
  duration: const Duration(seconds: 2),
);

// 粒子更新动画
_particleController = AnimationController(
  vsync: this,
  duration: const Duration(milliseconds: 50),
)..addListener(_updateParticles);

// 脉冲呼吸动画
_pulseController = AnimationController(
  vsync: this,
  duration: const Duration(milliseconds: 1500),
)..repeat(reverse: true);

6.2 罗盘旋转动画

AnimatedBuilder(
  animation: _compassController,
  builder: (context, child) {
    final targetAngle = _currentWind!.direction.degree * pi / 180;
    final animationValue = Curves.easeOutCubic.transform(_compassController.value);
    final currentAngle = targetAngle * animationValue;

    return Transform.rotate(
      angle: currentAngle,
      child: CustomPaint(
        painter: ArrowPainter(color: Colors.cyan.shade300),
      ),
    );
  },
)

6.3 动画时序图

启动阶段 0ms 初始化动画控制器 0ms 生成初始风数据 0ms 生成粒子系统 运行阶段 每50ms 更新粒子位置 每5秒 更新风数据 更新时 罗盘旋转动画 持续阶段 持续 脉冲呼吸效果 持续 粒子流动效果 风的方向动画时序

七、风之诗系统

7.1 诗句映射

根据风速等级生成不同的诗句:

风速 诗句
无风 风静叶无声
云淡天高远
一缕炊烟直
岁月正安然
微风 微风拂面来
轻摇树叶间
似有还无迹
春意正阑珊
轻风 轻风过林梢
枝叶舞翩跹
鸟鸣声声脆
心随自然闲
和风 和风送清凉
尘土舞飞扬
旗帜猎猎响
天地正苍茫
清风 清风拂大地
水波荡涟漪
小树随风舞
心旷神怡时
强风 强风撼大树
举步显艰难
风中行路人
意志更坚强
疾风 疾风扫落叶
树枝折断声
天地变色时
唯有心不惊
大风 大风起兮云飞扬
威加海内兮归故乡
安得猛士兮守四方

7.2 诗句生成逻辑

String _getWindPoetry() {
  if (_currentWind == null) return '';

  final poetries = {
    WindSpeed.calm: '风静叶无声\n云淡天高远\n一缕炊烟直\n岁月正安然',
    WindSpeed.light: '微风拂面来\n轻摇树叶间\n似有还无迹\n春意正阑珊',
    // ... 更多诗句
  };

  return poetries[_currentWind!.speed] ?? '';
}

八、状态管理

8.1 状态分类

状态类型 状态名称 说明
当前风数据 _currentWind 当前风向风速
历史记录 _windHistory 24小时历史
粒子列表 _particles 粒子系统数据
风数据定时器 _windTimer 定时更新风数据

8.2 数据更新流程

界面 状态管理 数据生成器 定时器 界面 状态管理 数据生成器 定时器 每5秒触发 生成风向角度 生成风速值 计算风向风速等级 更新当前风数据 添加到历史记录 刷新界面 罗盘旋转动画

九、性能优化

9.1 渲染优化

优化点 实现方式 效果
粒子数量 限制50个粒子 控制渲染量
重绘策略 shouldRepaint返回true 实时更新
定时器管理 及时取消Timer 避免内存泄漏
动画释放 dispose中释放 释放资源

9.2 内存管理


void dispose() {
  _windTimer?.cancel();
  _compassController.dispose();
  _particleController.dispose();
  _pulseController.dispose();
  super.dispose();
}

9.3 性能指标

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

十、常见问题

10.1 问题排查

问题 原因 解决方案
罗盘不旋转 动画未启动 检查_animateCompass
粒子不移动 更新未触发 检查_updateParticles
风向错误 角度计算错误 检查fromDegree方法
内存泄漏 Timer未取消 在dispose中取消

10.2 调试技巧

// 打印风数据
debugPrint('Direction: ${_currentWind?.direction.label}');
debugPrint('Speed: ${_currentWind?.speedValue} m/s');
debugPrint('Speed Level: ${_currentWind?.speed.label}');

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

// 打印历史记录
debugPrint('History: ${_windHistory.length} records');

十一、运行说明

11.1 环境要求

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

11.2 运行命令

# 查看可用设备
flutter devices

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

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

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

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

十二、扩展建议

12.1 功能扩展

功能 优先级 实现思路
真实天气API 接入天气服务API
地理定位 获取用户位置
风向预报 未来风向预测
历史记录 本地数据存储
分享功能 分享风向信息
语音播报 语音播报风向

12.2 设计扩展

方向 描述
更多主题 日出、日落、星空等主题
音效反馈 风声音效
振动反馈 风速振动
AR效果 增强现实风向显示

12.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 风向罗盘 粒子动画 风之诗系统 真实天气API 地理定位 数据持久化 风向预报 音效系统 分享功能 V1.0 基础版本 V1.1 数据版本 V1.2 增强版本 风的方向应用开发计划

十三、自然科学价值

13.1 应用价值

风的方向应用具有重要的自然科学价值:

  1. 气象认知:帮助用户了解风向风速的基本概念
  2. 自然感知:增强用户对自然环境的感知能力
  3. 诗意生活:将科学与艺术结合,提升生活品质
  4. 环保意识:培养关注自然、保护环境的意识

13.2 教育意义

风的方向

科学知识

气象学基础

风向测量

风速分级

自然感知

观察自然

感受变化

理解规律

艺术体验

风之诗

视觉美感

心灵慰藉

13.3 使用场景

场景 适用人群 预期效果
户外活动 登山者、帆船爱好者 了解风况,规划活动
气象学习 学生群体 学习气象知识
休闲放松 都市人群 感受自然,放松心情
艺术创作 文艺爱好者 获取灵感,创作作品

十四、总结

风的方向应用通过风向罗盘、粒子动画、风之诗等创新元素,为用户提供了一种独特的自然体验方式。应用核心亮点包括:

14.1 核心特色

  1. 风向罗盘:可视化风向显示,直观易懂
  2. 八级风速:科学分级,详细描述
  3. 粒子动画:动态展示风的流动
  4. 风向历史:24小时变化趋势
  5. 风之诗:科学与艺术的完美结合

14.2 技术亮点

  • 枚举类型设计:风向、风速使用枚举,代码清晰
  • 角度计算算法:精确的风向角度映射
  • 粒子系统:流畅的风流动画效果
  • CustomPainter:高效的自定义绘制
  • 动画控制器:多个动画协同工作

14.3 应用价值

风的方向不仅是一个气象工具,更是一次关于自然与艺术的探索。它让我们重新认识风这位自然的朋友,在科技的帮助下感受自然的韵律与诗意。

听风的声音,感受自然的呼吸!


愿每一阵风都能带来心灵的宁静 🌬️


Logo

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

更多推荐