Flutter 框架跨平台鸿蒙开发 - 年度听歌DNA应用
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net运行效果图年度听歌DNA应用是一款音乐品味分析与个人音乐画像生成应用,灵感来源于各大音乐平台的年度报告功能。应用通过分析用户的听歌数据,从音乐风格、情绪偏好、听歌习惯等多维度绘制用户的专属音乐DNA图谱,生成独特的个人音乐画像。应用以Spotify标志性的绿色为主色调,采用深色主题设计,营
年度听歌DNA应用
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
一、项目概述
运行效果图



1.1 应用简介
年度听歌DNA应用是一款音乐品味分析与个人音乐画像生成应用,灵感来源于各大音乐平台的年度报告功能。应用通过分析用户的听歌数据,从音乐风格、情绪偏好、听歌习惯等多维度绘制用户的专属音乐DNA图谱,生成独特的个人音乐画像。
应用以Spotify标志性的绿色为主色调,采用深色主题设计,营造沉浸式的音乐氛围。涵盖概览、DNA分析、年度榜单、听歌洞察四大模块,支持10种音乐风格分类和6种情绪分析,通过雷达图、进度条、卡片列表等多种可视化方式呈现用户的音乐基因。
1.2 核心功能
| 功能模块 | 功能描述 | 实现方式 |
|---|---|---|
| 概览页面 | 年度统计与音乐人格展示 | CustomScrollView |
| DNA分析 | 风格雷达图与分布分析 | CustomPainter |
| 年度榜单 | TOP10歌曲与TOP5歌手 | 卡片列表 |
| 听歌洞察 | 听歌习惯与行为分析 | 洞察卡片 |
| 音乐人格 | 个人音乐画像生成 | 数据分析 |
| 分享报告 | 年度报告分享功能 | 弹窗展示 |
1.3 音乐风格分类
| 序号 | 风格名称 | Emoji | 主题色 | 代表艺人 |
|---|---|---|---|---|
| 1 | 流行 | 🎤 | #FF6B6B | 周杰伦、Taylor Swift |
| 2 | 摇滚 | 🎸 | #4ECDC4 | Queen、Led Zeppelin |
| 3 | 嘻哈 | 🎧 | #FFE66D | Eminem、Travis Scott |
| 4 | 电子 | 🎹 | #95E1D3 | Alan Walker、Deadmau5 |
| 5 | R&B | 🎷 | #DDA0DD | The Weeknd、Beyoncé |
| 6 | 古典 | 🎻 | #B8860B | 贝多芬、维瓦尔第 |
| 7 | 爵士 | 🎺 | #87CEEB | Miles Davis、Dave Brubeck |
| 8 | 民谣 | 🪕 | #98D8C8 | 赵雷、马頔 |
| 9 | 金属 | 🤘 | #2C3E50 | Metallica |
| 10 | 乡村 | 🤠 | #F4A460 | John Denver、Dolly Parton |
1.4 情绪分析类型
| 序号 | 情绪类型 | Emoji | 主题色 | 听歌场景 |
|---|---|---|---|---|
| 1 | 活力四射 | ⚡ | #FF6B6B | 运动、派对 |
| 2 | 慵懒放松 | 🌙 | #6C5CE7 | 休息、睡前 |
| 3 | 浪漫甜蜜 | 💕 | #FD79A8 | 约会、纪念日 |
| 4 | 忧郁深沉 | 🌧️ | #74B9FF | 独处、思考 |
| 5 | 专注沉浸 | 🎯 | #00B894 | 工作、学习 |
| 6 | 怀旧感伤 | 📷 | #FDCB6E | 回忆、思念 |
1.5 技术栈
| 技术领域 | 技术选型 | 版本要求 |
|---|---|---|
| 开发框架 | Flutter | >= 3.0.0 |
| 编程语言 | Dart | >= 2.17.0 |
| 设计规范 | Material Design 3 | - |
| 图表绘制 | CustomPainter | - |
| 动画控制 | AnimationController | - |
| 状态管理 | setState | - |
| 目标平台 | 鸿蒙OS / Web | API 21+ |
1.6 项目结构
lib/
└── main_music_dna.dart
├── MusicDNAApp # 应用入口
├── MusicGenre # 音乐风格枚举
├── ListeningMood # 情绪类型枚举
├── SongRecord # 歌曲记录数据模型
├── MusicDNAProfile # 音乐DNA画像模型
├── MusicDNAHomePage # 主页面(底部导航)
├── _buildOverviewPage # 概览页面
├── _buildDNAAnalysisPage # DNA分析页面
├── _buildTopChartsPage # 榜单页面
├── _buildInsightsPage # 洞察页面
└── RadarChartPainter # 雷达图绘制器
二、系统架构
2.1 整体架构图
2.2 类图设计
2.3 页面导航流程
2.4 数据流向图
三、核心模块设计
3.1 数据模型设计
3.1.1 音乐风格枚举 (MusicGenre)
enum MusicGenre {
pop('流行', Color(0xFFFF6B6B), '🎤'),
rock('摇滚', Color(0xFF4ECDC4), '🎸'),
hiphop('嘻哈', Color(0xFFFFE66D), '🎧'),
electronic('电子', Color(0xFF95E1D3), '🎹'),
rnb('R&B', Color(0xFFDDA0DD), '🎷'),
classical('古典', Color(0xFFB8860B), '🎻'),
jazz('爵士', Color(0xFF87CEEB), '🎺'),
folk('民谣', Color(0xFF98D8C8), '🪕'),
metal('金属', Color(0xFF2C3E50), '🤘'),
country('乡村', Color(0xFFF4A460), '🤠');
final String label; // 风格名称
final Color color; // 主题颜色
final String emoji; // 代表表情
}
3.1.2 情绪类型枚举 (ListeningMood)
enum ListeningMood {
energetic('活力四射', '⚡', Color(0xFFFF6B6B)),
chill('慵懒放松', '🌙', Color(0xFF6C5CE7)),
romantic('浪漫甜蜜', '💕', Color(0xFFFD79A8)),
melancholy('忧郁深沉', '🌧️', Color(0xFF74B9FF)),
focused('专注沉浸', '🎯', Color(0xFF00B894)),
nostalgic('怀旧感伤', '📷', Color(0xFFFDCB6E));
final String label; // 情绪名称
final String emoji; // 代表表情
final Color color; // 主题颜色
}
3.1.3 歌曲记录模型 (SongRecord)
class SongRecord {
final String id; // 唯一标识
final String title; // 歌曲名称
final String artist; // 歌手名称
final MusicGenre genre; // 音乐风格
final int playCount; // 播放次数
final int durationSeconds; // 歌曲时长(秒)
final DateTime lastPlayed; // 最后播放时间
final ListeningMood? mood; // 情绪标签
}
3.1.4 音乐DNA画像模型 (MusicDNAProfile)
class MusicDNAProfile {
final String userId; // 用户ID
final int year; // 年份
final int totalSongs; // 总歌曲数
final int totalMinutes; // 总听歌时长(分钟)
final int uniqueArtists; // 独立歌手数
final int uniqueGenres; // 风格种类数
final Map<MusicGenre, double> genreDistribution; // 风格分布
final Map<ListeningMood, double> moodDistribution; // 情绪分布
final List<SongRecord> topSongs; // TOP歌曲
final List<String> topArtists; // TOP歌手
final String musicPersonality; // 音乐人格
final String dnaCode; // DNA码
final Map<String, dynamic> insights; // 洞察数据
}
3.1.5 音乐风格分布
3.2 页面结构设计
3.2.1 主页面布局
3.2.2 概览页面结构
3.2.3 DNA分析页面结构
3.2.4 年度榜单页面结构
3.3 雷达图绘制原理
四、UI设计规范
4.1 配色方案
应用采用Spotify标志性的绿色为主色调,深色背景营造沉浸式音乐氛围:
| 颜色类型 | 色值 | 用途 |
|---|---|---|
| 主色 | #1DB954 (Spotify Green) | 导航、强调元素 |
| 主色浅 | #1ED760 | 渐变过渡 |
| 背景深色 | #121212 | 页面背景 |
| 背景卡片 | #1E1E1E | 卡片背景 |
| 背景深紫 | #191414 | 渐变背景 |
4.2 音乐风格配色
| 风格类型 | 色值 | 情感表达 |
|---|---|---|
| 流行 | #FF6B6B | 热情活力 |
| 摇滚 | #4ECDC4 | 叛逆自由 |
| 嘻哈 | #FFE66D | 街头潮流 |
| 电子 | #95E1D3 | 科技未来 |
| R&B | #DDA0DD | 柔情浪漫 |
| 古典 | #B8860B | 典雅高贵 |
| 爵士 | #87CEEB | 轻松惬意 |
| 民谣 | #98D8C8 | 朴素真挚 |
| 金属 | #2C3E50 | 沉重力量 |
| 乡村 | #F4A460 | 自然朴实 |
4.3 字体规范
| 元素 | 字号 | 字重 | 颜色 |
|---|---|---|---|
| 应用标题 | 28px | Bold | #FFFFFF |
| 年份数字 | 24px | Bold | 主题色 |
| 音乐人格 | 32px | Bold | #FFFFFF |
| 页面标题 | 20px | Bold | #FFFFFF |
| 歌曲名称 | 14px | Medium | #FFFFFF |
| 歌手名称 | 12px | Regular | #9E9E9E |
| 洞察数值 | 24px | Bold | 主题色 |
4.4 组件规范
4.4.1 快速统计卡片
┌────────────┐ ┌────────────┐ ┌────────────┐
│ 🎵 │ │ ⏰ │ │ 👤 │
│ 2847 │ │ 1427 │ │ 156 │
│ 首歌曲 │ │ 小时 │ │ 位歌手 │
└────────────┘ └────────────┘ └────────────┘
4.4.2 音乐人格卡片
┌─────────────────────────────────────────────┐
│ DNA-2024-XK9M2 🧠 │
│ │
│ 你的音乐人格 │
│ │
│ 多元探索者 │
│ │
│ 你对音乐充满好奇心,喜欢探索不同风格... │
└─────────────────────────────────────────────┘
4.4.3 风格分布条
🎤 流行 ████████████████████░░░░ 25.0%
🎸 摇滚 ████████████░░░░░░░░░░░░ 15.0%
🎧 嘻哈 ██████████░░░░░░░░░░░░░░ 12.0%
🎹 电子 ████████░░░░░░░░░░░░░░░░ 10.0%
4.4.4 洞察卡片
┌─────────────────────────────────────────────┐
│ ┌──────┐ │
│ │ 🌙 │ 最佳听歌时段 │
│ └──────┘ │
│ 深夜 23点 │
│ 你是夜猫子型听众... │
└─────────────────────────────────────────────┘
4.4.5 TOP歌曲列表
┌─────────────────────────────────────────────┐
│ 🏆 年度最爱歌曲 │
├─────────────────────────────────────────────┤
│ ┌────┐ 晴天 🎤 98次 │
│ │ 1 │ 周杰伦 │
│ └────┘ │
├─────────────────────────────────────────────┤
│ ┌────┐ Bohemian Rhapsody 🎸 87次 │
│ │ 2 │ Queen │
│ └────┘ │
└─────────────────────────────────────────────┘
五、核心功能实现
5.1 雷达图绘制实现
class RadarChartPainter extends CustomPainter {
final List<double> values;
final List<String> labels;
final List<Color> colors;
void paint(Canvas canvas, Size size) {
final center = Offset(size.width / 2, size.height / 2);
final radius = min(size.width, size.height) / 2 - 40;
final angleStep = 2 * pi / values.length;
// 绘制背景网格(5层同心多边形)
for (int i = 1; i <= 5; i++) {
final path = Path();
final r = radius * i / 5;
for (int j = 0; j <= values.length; j++) {
final angle = j * angleStep - pi / 2;
final x = center.dx + r * cos(angle);
final y = center.dy + r * sin(angle);
if (j == 0) path.moveTo(x, y);
else path.lineTo(x, y);
}
canvas.drawPath(path, bgPaint);
}
// 绘制数据区域
final dataPath = Path();
for (int i = 0; i <= values.length; i++) {
final index = i % values.length;
final angle = index * angleStep - pi / 2;
final r = radius * (values[index] / 100).clamp(0.1, 1.0);
final x = center.dx + r * cos(angle);
final y = center.dy + r * sin(angle);
if (i == 0) dataPath.moveTo(x, y);
else dataPath.lineTo(x, y);
}
// 填充渐变色
canvas.drawPath(dataPath, fillPaint);
canvas.drawPath(dataPath, strokePaint);
}
}
5.2 旋转DNA图标动画
AnimatedBuilder(
animation: _rotateController,
builder: (context, child) {
return Transform.rotate(
angle: _rotateController.value * 2 * pi,
child: Container(
width: 120,
height: 120,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: SweepGradient(
colors: [
const Color(0xFF1DB954),
const Color(0xFF1ED760),
const Color(0xFF1DB954),
],
),
boxShadow: [
BoxShadow(
color: const Color(0xFF1DB954).withValues(alpha: 0.5),
blurRadius: 30,
spreadRadius: 10,
),
],
),
child: Center(child: Text('🎵', style: TextStyle(fontSize: 40))),
),
);
},
)
5.3 风格分布进度条
Widget _buildGenreDistribution() {
final sortedGenres = _profile.genreDistribution.entries.toList()
..sort((a, b) => b.value.compareTo(a.value));
return Column(
children: sortedGenres.map((entry) {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(children: [
Text(entry.key.emoji),
Text(entry.key.label),
]),
Text('${entry.value.toStringAsFixed(1)}%'),
],
),
ClipRRect(
borderRadius: BorderRadius.circular(4),
child: LinearProgressIndicator(
value: entry.value / 100,
backgroundColor: Colors.grey[800],
valueColor: AlwaysStoppedAnimation<Color>(entry.key.color),
minHeight: 8,
),
),
],
);
}).toList(),
);
}
5.4 音乐人格生成
MusicDNAProfile _generateSampleProfile() {
// 分析风格分布
final genreDist = <MusicGenre, double>{};
for (var genre in MusicGenre.values) {
genreDist[genre] = random.nextDouble() * 30 + 5;
}
final totalGenre = genreDist.values.reduce((a, b) => a + b);
genreDist.updateAll((key, value) => (value / totalGenre) * 100);
// 分析情绪分布
final moodDist = <ListeningMood, double>{};
for (var mood in ListeningMood.values) {
moodDist[mood] = random.nextDouble() * 25 + 5;
}
final totalMood = moodDist.values.reduce((a, b) => a + b);
moodDist.updateAll((key, value) => (value / totalMood) * 100);
// 生成DNA码
final dnaCode = 'DNA-${year}-${Random().nextInt(9000) + 1000}';
return MusicDNAProfile(
musicPersonality: '多元探索者',
dnaCode: dnaCode,
genreDistribution: genreDist,
moodDistribution: moodDist,
// ...其他数据
);
}
5.5 分享报告功能
void _shareReport() {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('分享年度报告'),
content: Container(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Text('🎵 我的${_profile.year}年度听歌DNA 🎵'),
Text('DNA码: ${_profile.dnaCode}'),
Text('听歌时长: ${(_profile.totalMinutes / 60).round()}小时'),
Text('音乐人格: ${_profile.musicPersonality}'),
],
),
),
actions: [
TextButton(onPressed: () => Navigator.pop(context), child: Text('关闭')),
FilledButton(onPressed: () {
// 复制到剪贴板
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('已复制到剪贴板')),
);
}, child: Text('复制')),
],
),
);
}
六、交互设计
6.1 页面切换流程
6.2 分享报告流程
6.3 雷达图交互
七、扩展功能规划
7.1 后续版本规划
7.2 功能扩展建议
7.2.1 真实数据接入
音乐平台API对接:
- 支持Spotify API获取听歌数据
- 支持Apple Music数据导入
- 支持网易云音乐数据解析
- 支持本地音乐库扫描
7.2.2 时间轴分析
时间维度分析:
- 按月份分析听歌趋势
- 按时段分析听歌习惯
- 按季节分析风格变化
- 生成时间轴可视化
7.2.3 社交分享
社交功能:
- 生成精美分享图片
- 支持微信、微博分享
- 好友音乐品味对比
- 音乐人格匹配度
八、注意事项
8.1 开发注意事项
-
雷达图绘制:使用CustomPainter时注意坐标系转换
-
动画控制:AnimationController需要在dispose时释放
-
颜色处理:使用withValues方法设置透明度
-
数据计算:风格分布百分比总和应为100%
-
性能优化:雷达图使用shouldRepaint控制重绘
8.2 常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 雷达图变形 | 尺寸计算错误 | 使用min(width, height) |
| 动画卡顿 | 未释放Controller | 在dispose中释放 |
| 颜色显示异常 | 透明度设置错误 | 使用withValues方法 |
| 百分比不正确 | 未归一化处理 | 除以总和再乘100 |
8.3 设计理念
🎵 设计理念 🎵
音乐是灵魂的语言,
每一首歌都是一段记忆,
每一个风格都是一种态度。
通过年度听歌DNA,
发现你的音乐基因,
探索你的音乐人格,
让数据讲述你的音乐故事。
九、运行说明
9.1 环境要求
| 环境 | 版本要求 |
|---|---|
| Flutter SDK | >= 3.0.0 |
| Dart SDK | >= 2.17.0 |
| 鸿蒙OS | API 21+ |
9.2 运行命令
# 查看可用设备
flutter devices
# 运行到Web服务器
flutter run -d web-server -t lib/main_music_dna.dart --web-port 8109
# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_music_dna.dart
# 运行到Edge浏览器
flutter run -d edge lib/main_music_dna.dart
# 代码分析
flutter analyze lib/main_music_dna.dart
十、总结
年度听歌DNA应用通过概览、DNA分析、年度榜单、听歌洞察四大模块,为用户提供了全方位的音乐品味分析与个人音乐画像生成服务。应用支持10种音乐风格分类和6种情绪分析,通过雷达图、进度条、卡片列表等多种可视化方式呈现用户的音乐基因。
核心功能涵盖年度统计展示、音乐人格生成、风格雷达图、情绪分析、TOP榜单、洞察报告六大模块。概览页面以动态DNA图标和快速统计卡片吸引用户;DNA分析页面通过自定义绘制的雷达图直观展示风格分布;榜单页面呈现年度最爱歌曲与歌手;洞察页面深入分析用户的听歌习惯与行为特征。
应用采用Material Design 3设计规范,以Spotify标志性的绿色为主色调,深色主题营造沉浸式音乐氛围。通过本应用,希望能够帮助用户发现属于自己的音乐基因,探索独特的音乐人格,让数据讲述每个人的音乐故事。
探索你的音乐基因
更多推荐




所有评论(0)