年度听歌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 整体架构图

Data Layer

Presentation Layer

主页面
MusicDNAHomePage

概览页面

DNA分析

年度榜单

听歌洞察

头部动画

快速统计

音乐人格

风格预览

雷达图

风格分布

情绪分析

TOP歌曲

TOP歌手

洞察卡片

年度总结

MusicDNAProfile
音乐画像

SongRecord
歌曲记录

MusicGenre
音乐风格

ListeningMood
情绪类型

2.2 类图设计

has

has

contains

analyzes

analyzes

displays

uses

MusicDNAApp

+Widget build()

«enumeration»

MusicGenre

+String label

+String emoji

+Color color

+pop()

+rock()

+hiphop()

+electronic()

+rnb()

+classical()

+jazz()

+folk()

+metal()

+country()

«enumeration»

ListeningMood

+String label

+String emoji

+Color color

+energetic()

+chill()

+romantic()

+melancholy()

+focused()

+nostalgic()

SongRecord

+String id

+String title

+String artist

+MusicGenre genre

+int playCount

+int durationSeconds

+DateTime lastPlayed

+ListeningMood? mood

MusicDNAProfile

+String userId

+int year

+int totalSongs

+int totalMinutes

+int uniqueArtists

+int uniqueGenres

+Map<MusicGenre,double> genreDistribution

+Map<ListeningMood,double> moodDistribution

+List<SongRecord> topSongs

+List<String> topArtists

+String musicPersonality

+String dnaCode

+Map<String,dynamic> insights

MusicDNAHomePage

-int _selectedIndex

-MusicDNAProfile _profile

-AnimationController _pulseController

-AnimationController _rotateController

+Widget build()

-_buildDNARadarChart()

-_generateSampleProfile()

-_shareReport()

RadarChartPainter

+List<double> values

+List<String> labels

+List<Color> colors

+void paint()

+bool shouldRepaint()

2.3 页面导航流程

概览

DNA

榜单

洞察

应用启动

概览页面

底部导航

年度统计

DNA分析

年度榜单

听歌洞察

音乐人格卡片

风格偏好预览

风格雷达图

风格分布条

情绪分析卡片

TOP10歌曲

TOP5歌手

洞察卡片列表

年度总结

分享报告

2.4 数据流向图

榜单页面 DNA分析 概览页面 用户 榜单页面 DNA分析 概览页面 用户 进入应用 加载音乐画像数据 展示年度统计 点击查看DNA 切换页面 绘制雷达图 展示风格分布 查看情绪分析 展示情绪分布 切换榜单 展示TOP歌曲/歌手 点击分享 生成分享卡片

三、核心模块设计

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 音乐风格分布
25% 15% 12% 10% 8% 8% 7% 6% 5% 4% 音乐风格分布示例 流行 摇滚 嘻哈 电子 R&B 古典 爵士 民谣 金属 乡村

3.2 页面结构设计

3.2.1 主页面布局

MusicDNAHomePage

IndexedStack

概览页面

DNA分析

年度榜单

听歌洞察

NavigationBar

概览 Tab

DNA Tab

榜单 Tab

洞察 Tab

3.2.2 概览页面结构

概览页面

SliverAppBar

快速统计

音乐人格

风格预览

旋转DNA图标

年度标题

粒子背景

歌曲数

听歌时长

歌手数

DNA码

人格类型

人格描述

3.2.3 DNA分析页面结构

DNA分析页面

风格雷达图

风格分布

情绪分析

CustomPainter绘制

十边形网格

数据填充区域

进度条列表

风格标签

百分比显示

情绪卡片网格

情绪图标

情绪百分比

3.2.4 年度榜单页面结构

年度榜单页面

TOP歌曲卡片

TOP歌手卡片

排名标识

歌曲信息

风格标签

播放次数

奖杯图标

歌手名称

排名颜色

3.3 雷达图绘制原理

坐标计算

开始绘制

计算中心点与半径

绘制背景网格

绘制轴线

计算数据点坐标

绘制填充区域

绘制边框线条

绘制数据点

绘制标签文字

绘制完成

角度 = 索引 * 步进角 - 90°

x = centerX + radius * cos角度

y = centerY + radius * sin角度


四、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 页面切换流程

洞察页面 榜单页面 DNA分析 概览页面 用户 洞察页面 榜单页面 DNA分析 概览页面 用户 进入应用 展示年度统计 点击查看DNA 切换Tab 展示雷达图 切换榜单Tab 切换Tab 展示TOP列表 切换洞察Tab 切换Tab 展示洞察卡片

6.2 分享报告流程

复制

关闭

点击分享按钮

弹出分享对话框

用户选择

复制报告文本

显示成功提示

关闭对话框

报告内容

DNA码

听歌时长

音乐人格

年度标签

6.3 雷达图交互

刷新数据

计算新坐标

绘制完成

静态展示

数据更新

重新绘制

显示当前风格分布
十边形网格背景
数据点与连线


七、扩展功能规划

7.1 后续版本规划

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 概览页面 DNA分析页面 榜单页面 洞察页面 真实数据接入 时间轴分析 对比功能 社交分享 好友对比 年度报告生成 V1.0 基础版本 V1.1 增强版本 V1.2 进阶版本 年度听歌DNA应用开发计划

7.2 功能扩展建议

7.2.1 真实数据接入

音乐平台API对接:

  • 支持Spotify API获取听歌数据
  • 支持Apple Music数据导入
  • 支持网易云音乐数据解析
  • 支持本地音乐库扫描
7.2.2 时间轴分析

时间维度分析:

  • 按月份分析听歌趋势
  • 按时段分析听歌习惯
  • 按季节分析风格变化
  • 生成时间轴可视化
7.2.3 社交分享

社交功能:

  • 生成精美分享图片
  • 支持微信、微博分享
  • 好友音乐品味对比
  • 音乐人格匹配度

八、注意事项

8.1 开发注意事项

  1. 雷达图绘制:使用CustomPainter时注意坐标系转换

  2. 动画控制:AnimationController需要在dispose时释放

  3. 颜色处理:使用withValues方法设置透明度

  4. 数据计算:风格分布百分比总和应为100%

  5. 性能优化:雷达图使用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标志性的绿色为主色调,深色主题营造沉浸式音乐氛围。通过本应用,希望能够帮助用户发现属于自己的音乐基因,探索独特的音乐人格,让数据讲述每个人的音乐故事。

探索你的音乐基因

Logo

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

更多推荐