Compare commits

30 Commits

Author SHA1 Message Date
DESKTOP-RQ919RC\Pc
577c9d967d no message 2025-12-10 18:17:00 +08:00
c351c887b9 修改名称为千军万马保永昌
Signed-off-by: chenfeilong <26522562@gmail.com>
2025-12-10 18:07:24 +08:00
DESKTOP-RQ919RC\Pc
899d0d04fa no message 2025-12-10 17:20:56 +08:00
DESKTOP-RQ919RC\Pc
c7cd36ff05 no message 2025-12-10 16:45:41 +08:00
DESKTOP-RQ919RC\Pc
3118a84750 no message 2025-12-10 16:42:40 +08:00
DESKTOP-RQ919RC\Pc
b334998413 no message 2025-12-10 16:37:57 +08:00
DESKTOP-RQ919RC\Pc
1334fa197f no message 2025-12-10 16:32:02 +08:00
DESKTOP-RQ919RC\Pc
8d664fcbea no message 2025-12-10 16:15:17 +08:00
7bf9b3af82 更新 h5/thousands.html 2025-12-10 07:09:09 +00:00
c7a37c5a42 添加 h5/thousands.html 2025-12-10 06:47:41 +00:00
551b282e41 更新 player.html 2025-12-09 15:29:38 +00:00
5293e7e295 更新 player.html 2025-12-09 14:15:08 +00:00
DESKTOP-RQ919RC\Pc
f692fbcc05 feat(player): 添加音乐播放器页面及核心功能实现
实现音乐播放器页面,包含以下核心功能:
1. 响应式唱片旋转动画和播放控制
2. 歌词同步显示和进度条拖动
3. 自动播放处理及移动端适配优化
4. 粒子效果和视觉优化
5. 元数据动态更新和错误处理
2025-12-09 15:19:48 +08:00
DESKTOP-RQ919RC\Pc
c057fb2f1d style(css): 优化.award .name元素的尺寸样式
调整.name元素的高度和宽度属性,使用max-height和max-width替代固定高度,并添加width: 100%和height: 100%使其更灵活适应不同尺寸
2025-12-08 11:21:13 +08:00
DESKTOP-RQ919RC\Pc
f1aa3a5d4a feat(ui): 优化标签样式并添加播放状态高亮效果
- 重构标签HTML结构,添加.tag-text容器
- 为当前播放标签添加旋转渐变边框效果
- 调整标签尺寸和内边距
- 添加控制台日志输出当前播放数据
- 更新VSCode端口配置
2025-10-11 18:54:11 +08:00
DESKTOP-RQ919RC\Pc
bccccacad8 fix(歌曲请求站): 修复歌曲切换逻辑并优化音频管理
修复fastForward函数逻辑,改为按标签切换歌曲而非时间跳转
调整clickSongs函数,传递标签信息用于后续歌曲管理
移除调试用的console.log语句
统一代码格式,如引号风格和分号使用
2025-10-11 12:03:39 +08:00
DESKTOP-RQ919RC\Pc
478e1c357c feat: 更新音乐站功能与资源
重构音乐数据格式,优化标签分类系统
新增多首音乐资源并完善标签关联
调整音频播放路径指向本地静态资源
2025-10-11 11:18:55 +08:00
DESKTOP-RQ919RC\Pc
84b0725720 style(css): 为全局样式添加 PingFang 字体
统一所有页面的默认字体为 "PingFangSC-Regular",确保跨平台显示一致性
2025-09-26 17:32:50 +08:00
DESKTOP-RQ919RC\Pc
e378e383f6 fix: 修复页面布局和交互问题
调整CSS样式改善元素对齐和文本换行
优化音频播放器进度条交互逻辑
移除未使用的代码和console.log
添加窗口大小变化的事件监听
修复标签云重新初始化问题
2025-09-25 18:53:56 +08:00
DESKTOP-RQ919RC\Pc
d61f57ed71 style(css): 为音频框内容添加 white-space 属性
添加 white-space: pre-wrap 以确保音频框中的文本正确换行显示
2025-09-25 17:15:37 +08:00
DESKTOP-RQ919RC\Pc
a034c3e6cf style(css): 更新字体族以包含PingFang字体
修改音频框序列号的字体族,添加PingFangSC-Regular和PingFang SC作为备选字体,确保在不同系统下显示一致
2025-09-25 16:42:15 +08:00
DESKTOP-RQ919RC\Pc
a2ee6e8e1f fix: 移除图片悬停动画并调整容器高度
移除图片的悬停缩放动画效果以提升性能
将容器高度从100vh改为100%并添加最小高度限制
2025-09-25 16:35:39 +08:00
DESKTOP-RQ919RC\Pc
08053e2211 style: 为图片元素添加圆角边框样式
在index.css和index.less中为.content .custom .list .item .info-img添加border-radius属性,使图片显示圆角效果,提升视觉美观度
2025-09-25 16:18:57 +08:00
DESKTOP-RQ919RC\Pc
c124ea1a29 no message 2025-09-25 16:16:08 +08:00
DESKTOP-RQ919RC\Pc
755bd09000 style(css): 更新序列号字体族以包含PingFang字体
修改CSS和LESS文件中.serial类的字体族,添加PingFangSC-Regular和PingFang SC作为备选字体,确保在不同平台下更好的显示效果
2025-09-25 16:13:40 +08:00
DESKTOP-RQ919RC\Pc
6f6d9ee487 111 2025-09-25 16:03:57 +08:00
DESKTOP-RQ919RC\Pc
55cd29620c no message 2025-09-25 16:02:30 +08:00
DESKTOP-RQ919RC\Pc
1658c40097 docs: 更新页脚的公司名称和版权信息 2025-09-25 15:38:59 +08:00
DESKTOP-RQ919RC\Pc
523547871e feat: 添加悬停动画效果并优化音频播放逻辑
为多个元素添加悬停动画效果,提升用户体验
重构音频播放逻辑,增加judgmentPlayUrl方法统一处理播放
更新HTML元数据,优化SEO和移动端适配
修改部分文案内容
2025-09-25 15:34:07 +08:00
DESKTOP-RQ919RC\Pc
c5abafdc86 no message 2025-09-25 14:54:44 +08:00
28 changed files with 3844 additions and 452 deletions

7
.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
*.zip
*.tar.gz
*.mp4
*.mp3
*.m4a
node_modules/
dist/

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"liveServer.settings.port": 5501
}

607
h5/thousands.html Normal file
View File

@@ -0,0 +1,607 @@
<!DOCTYPE html><html lang="zh-CN"><head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>千军万马保永昌 - 温州抗倭史诗</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;700&amp;family=Noto+Sans+SC:wght@300;400;500&amp;display=swap" rel="stylesheet"/>
<style>
body {
font-family: 'Noto Sans SC', sans-serif;
background: linear-gradient(135deg, #FFF8DC 0%, #F5F5DC 100%);
overflow-x: hidden;
}
.hero-title {
font-family: 'Noto Serif SC', serif;
background: linear-gradient(45deg, #8B4513, #CD7F32);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.lyrics-text {
font-family: 'Noto Serif SC', serif;
color: #8B4513;
line-height: 2;
}
.bg-canvas {
position: fixed;
top: 0;
left: 0;
z-index: -1;
}
.content-overlay {
position: relative;
z-index: 10;
}
.nav-item {
transition: all 0.3s ease;
}
.nav-item:hover {
transform: translateY(-2px);
color: #DC143C;
}
.card-hover {
transition: all 0.3s ease;
}
.card-hover:hover {
transform: translateY(-5px);
box-shadow: 0 20px 40px rgba(139, 69, 19, 0.2);
}
.pulse-animation {
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.7; }
}
.fade-in {
opacity: 0;
transform: translateY(30px);
}
.hero-image {
background-image: url('https://pjoss.x-php.com/20251210/f551cd20d2f0c2036c42d22b00711b05.png');
background-size: cover;
background-position: center;
background-attachment: fixed;
}
</style>
</head>
<body>
<!-- 背景动画画布 -->
<div id="bg-canvas" class="bg-canvas"></div>
<!-- 导航栏 -->
<nav class="fixed top-0 w-full bg-white/90 backdrop-blur-sm z-50 shadow-sm">
<div class="max-w-7xl mx-auto px-6 py-4">
<div class="flex justify-between items-center">
<div class="hero-title text-2xl font-bold">千军万马保永昌</div>
<div class="flex space-x-8">
<a href="#home" class="nav-item cursor-pointer">首页</a>
<a href="#lyrics" class="nav-item cursor-pointer">歌词</a>
<a href="#history" class="nav-item cursor-pointer">历史</a>
<a href="#music" class="nav-item cursor-pointer">音乐</a>
</div>
</div>
</div>
</nav>
<!-- 主要内容 -->
<div class="content-overlay">
<!-- 英雄区域 -->
<section id="home" class="hero-image min-h-screen flex items-center justify-center relative">
<div class="absolute inset-0 bg-black/30"></div>
<div class="relative z-10 text-center text-white px-6">
<h1 class="text-6xl md:text-8xl font-bold mb-6 fade-in" style="font-family: &#39;Noto Serif SC&#39;, serif;">千军万马保永昌</h1>
<p class="text-xl md:text-2xl mb-8 fade-in">温州抗倭史诗 · 非遗鼓词传承</p>
<div class="flex flex-col md:flex-row gap-4 justify-center fade-in">
<button onclick="playMusic()" class="bg-red-600 hover:bg-red-700 text-white px-8 py-3 rounded-full text-lg font-medium transition-all duration-300 transform hover:scale-105">
播放音乐
</button>
<button onclick="scrollToSection(&#39;lyrics&#39;)" class="bg-transparent border-2 border-white text-white hover:bg-white hover:text-gray-800 px-8 py-3 rounded-full text-lg font-medium transition-all duration-300">
查看古词
</button>
</div>
</div>
</section>
<!-- 歌词展示区域 -->
<section id="lyrics" class="py-20 px-6">
<div class="max-w-4xl mx-auto">
<h2 class="text-4xl font-bold text-center mb-16 hero-title fade-in">古词欣赏</h2>
<!-- 歌词卡片 -->
<div class="bg-white/80 backdrop-blur-sm rounded-2xl p-8 shadow-lg card-hover fade-in mb-8">
<div class="text-center mb-8">
<h3 class="text-2xl font-bold lyrics-text mb-4">【开篇】</h3>
<p class="lyrics-text text-lg">公元一五五八年,倭寇越来越嚣张。</p>
<p class="lyrics-text text-lg">烧杀抢掠恶做尽,沿海百姓遭祸殃。</p>
</div>
<div class="text-center mb-8">
<h3 class="text-2xl font-bold lyrics-text mb-4">【第一幕】</h3>
<p class="lyrics-text text-lg">王沛王德俩叔侄,满腔热血保家乡。</p>
<p class="lyrics-text text-lg">身中数矛热血涌,赤胆忠魂震东洋。</p>
</div>
<div class="text-center mb-8">
<h3 class="text-2xl font-bold lyrics-text mb-4">【第二幕】</h3>
<p class="lyrics-text text-lg">叔果叔杲意志强,筹款要建护城墙。</p>
<p class="lyrics-text text-lg">王氏遗孀倾囊助,为保家园添力量。</p>
</div>
<div class="text-center mb-8">
<h3 class="text-2xl font-bold lyrics-text mb-4">【第三幕】</h3>
<p class="lyrics-text text-lg">城堡坚固厚城墙,倭寇围困日久长。</p>
<p class="lyrics-text text-lg">砻糠替谷河面运,砻糠之计退敌强。</p>
</div>
<div class="text-center mb-8">
<h3 class="text-2xl font-bold lyrics-text mb-4">【第四幕】</h3>
<p class="lyrics-text text-lg">遗孀乘机率众出,突袭敌营上战场。</p>
<p class="lyrics-text text-lg">战鼓声声号角响,杀的倭寇魂魄消。</p>
</div>
<div class="text-center mb-8">
<h3 class="text-2xl font-bold lyrics-text mb-4">【结尾】</h3>
<p class="lyrics-text text-lg">一段鼓词情难尽,古人壮举永传扬。</p>
<p class="lyrics-text text-lg">家国安宁民康泰,温州处处保永昌。</p>
</div>
<div class="text-center">
<p class="lyrics-text text-sm">作者:陈继宁(温州市鼓词研究会会长)</p>
<p class="lyrics-text text-sm">2025-12-01</p>
</div>
</div>
<!-- 音乐控制 -->
<div class="text-center">
<div class="bg-white/60 backdrop-blur-sm rounded-full px-8 py-4 inline-flex items-center space-x-6 shadow-lg">
<button id="playBtn" onclick="togglePlay()" class="w-12 h-12 bg-red-600 hover:bg-red-700 text-white rounded-full flex items-center justify-center transition-all duration-300">
</button>
<div class="flex items-center space-x-2">
<span class="text-sm text-gray-600">00:00</span>
<div class="w-64 h-2 bg-gray-300 rounded-full">
<div id="progressBar" class="h-full bg-red-600 rounded-full" style="width: 0%"></div>
</div>
<span class="text-sm text-gray-600">04:32</span>
</div>
<button onclick="toggleMute()" class="w-10 h-10 bg-gray-200 hover:bg-gray-300 rounded-full flex items-center justify-center transition-all duration-300">
🔊
</button>
</div>
</div>
</div>
</section>
<!-- 历史背景区域 -->
<section id="history" class="py-20 px-6 bg-gradient-to-b from-transparent to-white/50">
<div class="max-w-6xl mx-auto">
<h2 class="text-4xl font-bold text-center mb-16 hero-title fade-in">历史背景</h2>
<div class="grid md:grid-cols-2 gap-12 items-center mb-16">
<div class="fade-in">
<img src="https://pjoss.x-php.com/20251210/de589ced94b90b32165b55673479aa52.png" alt="温州古城" class="w-full rounded-2xl shadow-lg"/>
</div>
<div class="fade-in">
<h3 class="text-2xl font-bold lyrics-text mb-6">温州抗倭历史</h3>
<p class="text-gray-700 leading-relaxed mb-4">
明朝洪武二年1369年倭寇首次进犯温州地区从此开启了温州人民长达数百年的抗倭斗争。
温州地处浙南沿海,拥有众多岛屿,成为倭寇侵扰的重灾区。
</p>
<p class="text-gray-700 leading-relaxed mb-4">
在这场艰苦卓绝的斗争中,涌现出无数英雄人物。王沛、王德叔侄率领乡勇抗倭,
最终壮烈牺牲;戚继光将军更是在温州地区屡败倭寇,创造了鸳鸯阵法,
为抗倭战争作出了巨大贡献。
</p>
<p class="text-gray-700 leading-relaxed">
温州人民用血肉之躯筑起了一道保卫家园的钢铁长城,
体现了中华民族团结抗倭的爱国主义精神和不怕牺牲的高尚品格。
</p>
</div>
</div>
<!-- 历史时间轴 -->
<div class="fade-in">
<h3 class="text-2xl font-bold text-center lyrics-text mb-12">重要历史节点</h3>
<div class="relative">
<div class="absolute left-1/2 transform -translate-x-1/2 h-full w-1 bg-gradient-to-b from-red-600 to-yellow-600"></div>
<div class="space-y-12">
<div class="flex items-center">
<div class="w-1/2 pr-8 text-right">
<div class="bg-white/80 backdrop-blur-sm rounded-lg p-6 shadow-lg card-hover">
<h4 class="text-xl font-bold text-red-600 mb-2">1369年</h4>
<p class="text-gray-700">倭寇首次进犯温州,攻击永嘉、乐清等地</p>
</div>
</div>
<div class="w-4 h-4 bg-red-600 rounded-full border-4 border-white shadow-lg"></div>
<div class="w-1/2 pl-8"></div>
</div>
<div class="flex items-center">
<div class="w-1/2 pr-8"></div>
<div class="w-4 h-4 bg-yellow-600 rounded-full border-4 border-white shadow-lg"></div>
<div class="w-1/2 pl-8">
<div class="bg-white/80 backdrop-blur-sm rounded-lg p-6 shadow-lg card-hover">
<h4 class="text-xl font-bold text-yellow-600 mb-2">1558年</h4>
<p class="text-gray-700">王沛、王德叔侄壮烈牺牲,英桥王氏建造永昌堡</p>
</div>
</div>
</div>
<div class="flex items-center">
<div class="w-1/2 pr-8 text-right">
<div class="bg-white/80 backdrop-blur-sm rounded-lg p-6 shadow-lg card-hover">
<h4 class="text-xl font-bold text-red-600 mb-2">1560年代</h4>
<p class="text-gray-700">戚继光率戚家军在温州地区屡败倭寇</p>
</div>
</div>
<div class="w-4 h-4 bg-red-600 rounded-full border-4 border-white shadow-lg"></div>
<div class="w-1/2 pl-8"></div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- 音乐文化区域 -->
<section id="music" class="py-20 px-6">
<div class="max-w-6xl mx-auto">
<h2 class="text-4xl font-bold text-center mb-16 hero-title fade-in">音乐文化</h2>
<div class="grid md:grid-cols-2 gap-12 items-center mb-16">
<div class="fade-in">
<h3 class="text-2xl font-bold lyrics-text mb-6">陈继宁</h3>
<p class="text-gray-700 leading-relaxed mb-4">
温州学传播大使,温州市社科联理事,温州市鼓词研究会会长,国家级非遗温州鼓词陈派传人
</p>
<h3 class="text-2xl font-bold lyrics-text mb-6">温州鼓词</h3>
<p class="text-gray-700 leading-relaxed mb-4">
温州鼓词是国家级非物质文化遗产,流行于浙江温州及其毗邻地区,
用温州方言表演,具有浓厚的地方色彩和独特的艺术风格。
</p>
<p class="text-gray-700 leading-relaxed mb-4">
表演形式以一人&#34;单档&#34;为主,艺人自弹牛筋琴伴奏说唱。
牛筋琴是温州独有的乐器,音色浑厚柔美,为鼓词赋予了无可替代的声韵特质。
</p>
<p class="text-gray-700 leading-relaxed">
《千军万马保永昌》这首歌融合了温州鼓词的元素,
通过现代音乐手法重新演绎传统文化,
让年轻一代能够更好地理解和传承这一宝贵的文化遗产。
</p>
</div>
<div class="fade-in">
<img src="https://pjoss.x-php.com/20251210/1bfead1f41b7e0b4a291ab2da46400f7.jpg" alt="传统乐器" class="w-full rounded-2xl shadow-lg"/>
</div>
</div>
<!-- 音乐特色 -->
<div class="grid md:grid-cols-3 gap-8 fade-in">
<div class="bg-white/80 backdrop-blur-sm rounded-2xl p-6 text-center shadow-lg card-hover">
<div class="w-16 h-16 bg-red-100 rounded-full flex items-center justify-center mx-auto mb-4">
<span class="text-2xl">🎵</span>
</div>
<h4 class="text-xl font-bold lyrics-text mb-3">民歌长调</h4>
<p class="text-gray-700 text-sm">悠扬婉转的旋律,体现温州山水的灵秀之气</p>
</div>
<div class="bg-white/80 backdrop-blur-sm rounded-2xl p-6 text-center shadow-lg card-hover">
<div class="w-16 h-16 bg-yellow-100 rounded-full flex items-center justify-center mx-auto mb-4">
<span class="text-2xl">🎸</span>
</div>
<h4 class="text-xl font-bold lyrics-text mb-3">摇滚力量</h4>
<p class="text-gray-700 text-sm">现代摇滚的节奏感,展现抗倭斗争的激昂斗志</p>
</div>
<div class="bg-white/80 backdrop-blur-sm rounded-2xl p-6 text-center shadow-lg card-hover">
<div class="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4">
<span class="text-2xl">🥁</span>
</div>
<h4 class="text-xl font-bold lyrics-text mb-3">鼓词韵律</h4>
<p class="text-gray-700 text-sm">传统鼓词的独特韵味,传承非遗文化精髓</p>
</div>
</div>
</div>
</section>
<!-- 页脚 -->
<footer class="bg-gray-800 text-white py-12">
<div class="max-w-6xl mx-auto px-6 text-center">
<div class="hero-title text-2xl font-bold mb-4">千军万马保永昌</div>
<p class="text-gray-400 mb-6">传承温州抗倭精神,弘扬非遗鼓词文化</p>
<div class="text-sm text-gray-500">
© 2025龙湾之光AI数字偶像大赛项目. 致敬历史,传承文化,创新发展.
</div>
</div>
</footer>
</div>
<script>
// 背景动画
let bgSketch = function(p) {
let particles = [];
let numParticles = 50;
p.setup = function() {
let canvas = p.createCanvas(p.windowWidth, p.windowHeight);
canvas.parent('bg-canvas');
// 初始化粒子
for (let i = 0; i < numParticles; i++) {
particles.push({
x: p.random(p.width),
y: p.random(p.height),
vx: p.random(-0.5, 0.5),
vy: p.random(-0.5, 0.5),
size: p.random(2, 6),
alpha: p.random(50, 150)
});
}
};
p.draw = function() {
p.clear();
// 绘制流动粒子
for (let particle of particles) {
p.fill(139, 69, 19, particle.alpha);
p.noStroke();
p.ellipse(particle.x, particle.y, particle.size);
// 更新位置
particle.x += particle.vx;
particle.y += particle.vy;
// 边界检测
if (particle.x < 0 || particle.x > p.width) particle.vx *= -1;
if (particle.y < 0 || particle.y > p.height) particle.vy *= -1;
}
// 绘制连接线
for (let i = 0; i < particles.length; i++) {
for (let j = i + 1; j < particles.length; j++) {
let dist = p.dist(particles[i].x, particles[i].y, particles[j].x, particles[j].y);
if (dist < 100) {
p.stroke(139, 69, 19, 50 * (1 - dist / 100));
p.strokeWeight(1);
p.line(particles[i].x, particles[i].y, particles[j].x, particles[j].y);
}
}
}
};
p.windowResized = function() {
p.resizeCanvas(p.windowWidth, p.windowHeight);
};
};
// 初始化背景动画
new p5(bgSketch);
// 页面加载完成后的动画
document.addEventListener('DOMContentLoaded', function() {
// 淡入动画
const fadeElements = document.querySelectorAll('.fade-in');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
anime({
targets: entry.target,
opacity: [0, 1],
translateY: [30, 0],
duration: 800,
easing: 'easeOutQuart',
delay: anime.stagger(200)
});
observer.unobserve(entry.target);
}
});
});
fadeElements.forEach(el => {
observer.observe(el);
});
// 平滑滚动
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
});
// 音乐播放控制
const AUDIO_URL = 'https://pjoss.x-php.com/20251210/1f5b3890c2c336bec63f9af90fe40ae2.mp3';
let isPlaying = false;
let isMuted = false;
let duration = 0;
const audio = new Audio(AUDIO_URL);
audio.preload = 'metadata';
audio.addEventListener('loadedmetadata', () => {
duration = isFinite(audio.duration) ? Math.floor(audio.duration) : 0;
const timeEls = document.querySelectorAll('.text-sm.text-gray-600');
if (timeEls[1]) {
timeEls[1].textContent = formatTime(duration);
}
});
audio.addEventListener('timeupdate', () => {
updateProgress();
});
audio.addEventListener('ended', () => {
isPlaying = false;
updatePlayButton();
updateProgress();
});
audio.addEventListener('error', () => {
showNotification('音频加载或播放失败');
});
function playMusic() {
audio.play().then(() => {
isPlaying = true;
updatePlayButton();
showNotification('音乐播放中...');
}).catch(() => {
showNotification('无法自动播放,请手动点击播放');
});
}
function togglePlay() {
if (isPlaying) {
pauseMusic();
} else {
playMusic();
}
}
function pauseMusic() {
audio.pause();
isPlaying = false;
updatePlayButton();
}
function toggleMute() {
isMuted = !isMuted;
audio.muted = isMuted;
const muteBtn = document.querySelector('button[onclick="toggleMute()"]');
muteBtn.textContent = isMuted ? '🔇' : '🔊';
}
function updatePlayButton() {
const playBtn = document.getElementById('playBtn');
playBtn.textContent = isPlaying ? '⏸' : '▶';
}
function updateProgress() {
const progressBar = document.getElementById('progressBar');
const d = duration || (isFinite(audio.duration) ? Math.floor(audio.duration) : 0);
const ct = Math.floor(audio.currentTime || 0);
const progress = d ? (ct / d) * 100 : 0;
progressBar.style.width = progress + '%';
const timeEls = document.querySelectorAll('.text-sm.text-gray-600');
if (timeEls[0]) {
timeEls[0].textContent = formatTime(ct);
}
if (timeEls[1] && d) {
timeEls[1].textContent = formatTime(d);
}
}
function formatTime(seconds) {
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
}
function scrollToSection(sectionId) {
const section = document.getElementById(sectionId);
if (section) {
section.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
}
function showNotification(message) {
// 创建通知元素
const notification = document.createElement('div');
notification.className = 'fixed top-24 right-6 bg-green-500 text-white px-6 py-3 rounded-lg shadow-lg z-50 transform translate-x-full transition-transform duration-300';
notification.textContent = message;
document.body.appendChild(notification);
// 显示动画
setTimeout(() => {
notification.classList.remove('translate-x-full');
}, 100);
// 隐藏动画
setTimeout(() => {
notification.classList.add('translate-x-full');
setTimeout(() => {
document.body.removeChild(notification);
}, 300);
}, 3000);
}
// 滚动时的视差效果
window.addEventListener('scroll', function() {
const scrolled = window.pageYOffset;
const parallax = document.querySelector('.hero-image');
if (parallax) {
const speed = scrolled * 0.5;
parallax.style.transform = `translateY(${speed}px)`;
}
});
// 导航栏滚动效果
let lastScrollTop = 0;
window.addEventListener('scroll', function() {
const nav = document.querySelector('nav');
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
if (scrollTop > lastScrollTop && scrollTop > 100) {
// 向下滚动,隐藏导航栏
nav.style.transform = 'translateY(-100%)';
} else {
// 向上滚动,显示导航栏
nav.style.transform = 'translateY(0)';
}
lastScrollTop = scrollTop;
});
// 键盘快捷键
document.addEventListener('keydown', function(e) {
if (e.code === 'Space') {
e.preventDefault();
togglePlay();
} else if (e.code === 'KeyM') {
e.preventDefault();
toggleMute();
}
});
// 页面可见性变化处理
document.addEventListener('visibilitychange', function() {
if (document.hidden && isPlaying) {
// 页面隐藏时暂停音乐
pauseMusic();
}
});
// 页面加载时预加载资源
window.addEventListener('load', function() {
// preloadImages();
// 添加加载完成动画
anime({
targets: 'body',
opacity: [0, 1],
duration: 1000,
easing: 'easeOutQuart'
});
});
</script>
</body></html>

View File

@@ -1,14 +1,40 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- 基本元数据 -->
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>朴见潮音官网</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="format-detection" content="telephone=no,email=no,address=no" />
<meta name="renderer" content="webkit" />
<meta name="force-rendering" content="webkit" />
<meta name="theme-color" content="#1e135e" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<!-- 网站标题和描述 -->
<title>朴见潮音官网 - AI音乐创作先锋品牌</title>
<meta name="description" content="朴见潮音是国内领先的AI音乐创作品牌致力于通过人工智能技术推动音乐创作的创新与发展。" />
<meta name="keywords" content="朴见潮音,AI音乐,人工智能音乐,音乐创作,AI作曲" />
<meta name="author" content="朴见潮音" />
<!-- 社交媒体元数据 -->
<meta property="og:title" content="朴见潮音官网 - AI音乐创作先锋品牌" />
<meta property="og:description" content="朴见潮音是国内领先的AI音乐创作品牌致力于通过人工智能技术推动音乐创作的创新与发展。" />
<meta property="og:image" content="./static/img/logo.png" />
<meta property="og:url" content="https://www.pujian.com" />
<meta property="og:type" content="website" />
<meta property="og:site_name" content="朴见潮音" />
<!-- 网站图标 -->
<link rel="shortcut icon" href="./static/img/favicon.ico" type="image/x-icon" />
<link rel="apple-touch-icon" href="./static/img/logo.png" />
<link rel="icon" href="./static/img/favicon.ico" type="image/x-icon" />
<script src="./static/js/vue.global.js"></script>
<script src="./static/js/artplayer.js"></script>
<script src="./static/js/axios.min.js"></script>
<link rel="stylesheet" href="./static/css/index.css" />
<link rel="icon" href="./static/img/favicon.ico" type="image/x-icon" />
<style>
[v-cloak] {
display: none;
@@ -127,7 +153,7 @@
<div class="operate flexcenter">
<img class="speed left" src="./static/img/speed-left.png" @click="fastForward('slow')" />
<img v-if="item.state" class="play" @click="closeAll()" src="./static/img/pause-black-icon.svg" />
<img v-else class="play" @click="manageAudio(item.playurl, 'works')" src="./static/img/play-black-icon.svg" />
<img v-else class="play" @click="judgmentPlayUrl(item.playurl, 'works', index)" src="./static/img/play-black-icon.svg" />
<img class="speed right" src="./static/img/speed-right.png" @click="fastForward('fast')" />
</div>
</div>
@@ -140,7 +166,7 @@
<div class="custom" ref="customRef">
<div class="custom-box mar1200 flexflex">
<img class="title" src="./static/img/custom-title.png" />
<div class="subtitle">往事可成追忆,把你的故事谱成歌</div>
<div class="subtitle">释放音乐本能,用词曲表达人生</div>
<div class="list flexflex mar1200">
<div class="item flexacenter" v-for="(item, index) in customList" :key="index">
<div class="info flexflex">
@@ -153,7 +179,7 @@
<div class="operate flexcenter">
<img class="speed left" @click="fastForward('slow')" src="./static/img/speed-left.png" />
<img v-if="item.state" class="play" @click="closeAll()" src="./static/img/pause-black-icon.svg" />
<img v-else class="play" @click="item.playurl ? manageAudio(item.playurl, 'custom') : getPlayUrl(index, 'custom')" src="./static/img/play-black-icon.svg" />
<img v-else class="play" @click="judgmentPlayUrl(item.playurl, 'custom', index)" src="./static/img/play-black-icon.svg" />
<img class="speed right" @click="fastForward('fast')" src="./static/img/speed-right.png" />
</div>
</div>
@@ -190,7 +216,7 @@
<img class="cut left" src="./static/img/cut-left.svg" @click="cutSong('up', zeroOrderStudents.order)" />
<img class="speed left" src="./static/img/speed-white-left.png" @click="fastForward('slow')" />
<img v-if="zeroOrderStudents.state" class="play" @click="closeAll()" src="./static/img/pause-white-icon.svg" />
<img v-else class="play" @click="zeroOrderStudents.playurl ? manageAudio(zeroOrderStudents.playurl, 'student') : getPlayUrl(index, 'student')" src="./static/img/play-white-icon.svg" />
<img v-else class="play" @click="judgmentPlayUrl(zeroOrderStudents.playurl, 'student', index)" src="./static/img/play-white-icon.svg" />
<img class="speed right" src="./static/img/speed-white-right.png" @click="fastForward('fast')" />
<img class="cut right" src="./static/img/cut-right.svg" @click="cutSong('down', zeroOrderStudents.order)" />
</div>
@@ -207,7 +233,7 @@
<div class="footer flexcenter">
<img class="logo" src="./static/img/ai-title.png" />
<div class="text">广州九微科技有限公司 | Copyright 2001-2025 GTER All Rights Reserved | 粤ICP备14050432号</div>
<div class="text">广州朴见潮音工作室 | Copyright 2025 PUJIANCHAOYIN All Rights Reserved</div>
</div>
<div v-if="previewState" class="preview flexcenter" @click="closePreview()">
@@ -224,8 +250,8 @@
<div class="bottom-middle flexcenter">
<div class="flexacenter" style="margin-bottom: 10px">
<div class="time-display">{{ currentTimeFormatted }}</div>
<div class="progress-bar flexacenter" @click="handleBarDragBottomClick">
<div class="bar white" :style="{ width: progress + '%' }" @mousedown="startBarDragBottom"></div>
<div class="progress-bar flexacenter" @mousedown="startBarDragBottom">
<div class="bar white" :style="{ width: progress + '%' }"></div>
<div class="bar black flex1"></div>
</div>
<div class="time-display">{{ durationFormatted }}</div>

2448
player.html Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -47,7 +47,9 @@
<div class="fill-item" v-for="(item, index) in tagsFill" :key="index" :class="[`item${ item.type }`]"></div>
</div>
<div class="list" id="bubbleContainer" ref="container">
<div class="tag-item" v-for="(item, index) in tags" :key="index" :class="[`item${ item.type }`, {'red': item.isred}]" @click="clickSongs(item.songs)" @mouseleave="handleMouseleave" @mouseenter="handleMouseenter">{{ item.tag }}</div>
<div class="tag-item" v-for="(item, index) in tags" :key="index" :class="[`item${ item.type }`, {'red': item.isred},{'show': playData?.tag == item.tag}]" @click="clickSongs(item.tag, item.songs)" @mouseleave="handleMouseleave" @mouseenter="handleMouseenter">
<div class="tag-text">{{ item.tag }}</div>
</div>
</div>
</div>

View File

@@ -2,6 +2,7 @@
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
}
:root {
--base-height: 500px;
@@ -39,7 +40,7 @@
}
.container .container-box {
padding-top: 24px;
height: 100vh;
height: 100%;
display: flex;
flex-direction: column;
}
@@ -53,13 +54,14 @@
position: relative;
width: 1200px;
height: 280px;
min-height: 280px;
border-radius: 20px;
margin-bottom: 20px;
}
.container .container-box .header::after {
content: "";
width: 1200px;
height: 280px;
height: 100%;
background: linear-gradient(180deg, #7d4bf8 0%, #5241b0 100%);
border-radius: 20px;
position: absolute;
@@ -218,7 +220,6 @@
left: 997px;
}
.container .container-box .details {
max-height: 500px;
margin-bottom: 40px;
width: 1200px;
border-radius: 20px;
@@ -228,6 +229,7 @@
padding: 3px;
overflow: hidden;
height: var(--base-height);
min-height: var(--base-height);
}
.container .container-box .details::after {
content: "";

View File

@@ -2,6 +2,7 @@
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
}
:root {
@@ -48,7 +49,7 @@
.container-box {
padding-top: 24px;
height: 100vh;
height: 100%;
display: flex;
flex-direction: column;
@@ -63,6 +64,7 @@
position: relative;
width: 1200px;
height: 280px;
min-height: 280px;
// background: linear-gradient(180deg, #7d4bf8 0%, #5241b0 100%);
border-radius: 20px;
margin-bottom: 20px;
@@ -70,7 +72,7 @@
&::after {
content: "";
width: 1200px;
height: 280px;
height: 100%;
background: linear-gradient(180deg, rgba(125, 75, 248, 1) 0%, rgba(82, 65, 176, 1) 100%);
border-radius: 20px;
position: absolute;
@@ -251,7 +253,7 @@
.details {
// height: 500px;
// flex: 1;
max-height: 500px;
// max-height: 500px;
margin-bottom: 40px;
width: 1200px;
border-radius: 20px;
@@ -261,6 +263,7 @@
padding: 3px;
overflow: hidden;
height: var(--base-height);
min-height: var(--base-height);
&::after {
content: "";

View File

@@ -2,6 +2,7 @@
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
}
.content .flexflex {
display: flex;
@@ -80,6 +81,7 @@
.content .introduce .box .info .award {
flex-direction: column;
margin-bottom: 177px;
align-items: flex-start;
}
.content .introduce .box .info .award .title {
width: 101px;
@@ -87,8 +89,11 @@
margin-bottom: 25px;
}
.content .introduce .box .info .award .name {
height: 65px;
max-height: 65px;
max-width: 340px;
margin-bottom: 30px;
width: 100%;
height: 100%;
}
.content .introduce .box .info .award .explain {
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
@@ -137,6 +142,9 @@
border-radius: 15px;
overflow: hidden;
}
.content .introduce .box .album .album-box .item:hover .img {
transform: scale(1.05);
}
.content .introduce .box .album .album-box .item .bj.bj3 {
width: 101%;
height: 101%;
@@ -158,6 +166,7 @@
.content .introduce .box .album .album-box .item .img {
width: 100%;
height: 100%;
transition: all 0.3s ease-in-out;
}
.content .introduce .box .album .album-box .item .play {
width: 26px;
@@ -274,6 +283,9 @@
width: 402px;
height: 64px;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
}
.content .works .name-box .bj {
position: absolute;
@@ -283,11 +295,6 @@
z-index: -1;
}
.content .works .name-box .title {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 208px;
height: 49px;
}
.content .works .name-box .line {
@@ -352,7 +359,7 @@
}
.content .works .mv-box .item .serial {
height: 44px;
font-family: "AlibabaPuHuiTiB", "Alibaba PuHuiTi Bold", "Alibaba PuHuiTi Heavy", "Alibaba PuHuiTi", sans-serif;
font-family: "AlibabaPuHuiTiB", "Alibaba PuHuiTi Bold", "Alibaba PuHuiTi Heavy", "Alibaba PuHuiTi", "PingFangSC-Regular", "PingFang SC", sans-serif;
font-weight: 700;
font-style: normal;
color: #000000;
@@ -446,7 +453,7 @@
}
.content .works .audio-box .item .serial {
height: 44px;
font-family: "AlibabaPuHuiTiB", "Alibaba PuHuiTi Bold", "Alibaba PuHuiTi Heavy", "Alibaba PuHuiTi", sans-serif;
font-family: "AlibabaPuHuiTiB", "Alibaba PuHuiTi Bold", "Alibaba PuHuiTi Heavy", "Alibaba PuHuiTi", "PingFangSC-Regular", "PingFang SC", sans-serif;
font-weight: 700;
font-style: normal;
color: #000000;
@@ -492,6 +499,7 @@
font-size: 14px;
color: #555555;
margin-bottom: 8px;
white-space: pre-wrap;
}
.content .works .audio-box .item .content .info .time {
font-size: 14px;
@@ -532,6 +540,12 @@
background-color: #000000;
border-radius: 0 10px 10px 0;
}
.content .works .audio-box .item .content .info .operate {
transition: all 0.3s ease-in-out;
}
.content .works .audio-box .item .content .info .operate > img:hover {
transform: scale(1.1);
}
.content .works .audio-box .item .content .info .operate .speed {
width: 16px;
height: 12px;
@@ -611,6 +625,7 @@
font-size: 14px;
color: #555555;
margin-bottom: 18px;
white-space: pre-wrap;
}
.content .custom .list .item .info .progress-bar {
width: 260px;
@@ -646,6 +661,12 @@
background-color: #000000;
border-radius: 0 10px 10px 0;
}
.content .custom .list .item .info .operate {
transition: all 0.3s ease-in-out;
}
.content .custom .list .item .info .operate > img:hover {
transform: scale(1.1);
}
.content .custom .list .item .info .operate .speed {
width: 16px;
height: 12px;
@@ -661,6 +682,7 @@
width: 240px;
height: 240px;
filter: drop-shadow(5px 5px 2.5px rgba(0, 0, 0, 0.35));
border-radius: 10px;
}
.content .custom .bottom {
position: absolute;
@@ -703,6 +725,9 @@
cursor: pointer;
transition: all 0.3s ease-in-out;
}
.content .student .student-box .list .img:hover {
transform: scale(1.1);
}
.content .student .student-box .list .img.img5 {
left: 0;
z-index: 2;
@@ -792,6 +817,12 @@
background-color: #ffffff;
border-radius: 0 10px 10px 0;
}
.content .student .student-box .operate {
transition: all 0.3s ease-in-out;
}
.content .student .student-box .operate > img:hover {
transform: scale(1.1);
}
.content .student .student-box .operate .cut {
width: 14px;
height: 12px;

View File

@@ -2,6 +2,7 @@
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
}
.content {
@@ -91,6 +92,8 @@
.award {
flex-direction: column;
margin-bottom: 177px;
align-items: flex-start;
.title {
width: 101px;
height: 24px;
@@ -98,9 +101,11 @@
}
.name {
// width: min-content;
height: 65px;
max-height: 65px;
max-width: 340px;
margin-bottom: 30px;
width: 100%;
height: 100%;
}
.explain {
@@ -154,6 +159,12 @@
border-radius: 15px;
overflow: hidden;
&:hover {
.img {
transform: scale(1.05);
}
}
.bj {
&.bj3 {
width: 101%;
@@ -180,6 +191,7 @@
.img {
width: 100%;
height: 100%;
transition: all 0.3s ease-in-out;
}
.play {
@@ -315,6 +327,9 @@
width: 402px;
height: 64px;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
.bj {
position: absolute;
@@ -325,11 +340,11 @@
}
.title {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 208px;
// position: absolute;
// top: 50%;
// left: 50%;
// transform: translate(-50%, -50%);
// width: 208px;
height: 49px;
}
@@ -406,7 +421,7 @@
.serial {
height: 44px;
font-family: "AlibabaPuHuiTiB", "Alibaba PuHuiTi Bold", "Alibaba PuHuiTi Heavy", "Alibaba PuHuiTi", sans-serif;
font-family: "AlibabaPuHuiTiB", "Alibaba PuHuiTi Bold", "Alibaba PuHuiTi Heavy", "Alibaba PuHuiTi", "PingFangSC-Regular", "PingFang SC", sans-serif;
font-weight: 700;
font-style: normal;
color: #000000;
@@ -470,7 +485,6 @@
height: 100%;
border-radius: 10px;
transition: all 0.3s ease-in-out;
}
.play {
@@ -516,7 +530,7 @@
.serial {
height: 44px;
font-family: "AlibabaPuHuiTiB", "Alibaba PuHuiTi Bold", "Alibaba PuHuiTi Heavy", "Alibaba PuHuiTi", sans-serif;
font-family: "AlibabaPuHuiTiB", "Alibaba PuHuiTi Bold", "Alibaba PuHuiTi Heavy", "Alibaba PuHuiTi", "PingFangSC-Regular", "PingFang SC", sans-serif;
font-weight: 700;
font-style: normal;
color: #000000;
@@ -566,6 +580,7 @@
font-size: 14px;
color: #555555;
margin-bottom: 8px;
white-space: pre-wrap;
}
.time {
@@ -614,6 +629,11 @@
}
.operate {
transition: all 0.3s ease-in-out;
> img:hover {
transform: scale(1.1);
}
.speed {
width: 16px;
height: 12px;
@@ -706,6 +726,7 @@
font-size: 14px;
color: #555555;
margin-bottom: 18px;
white-space: pre-wrap;
}
.progress-bar {
@@ -748,6 +769,12 @@
}
.operate {
transition: all 0.3s ease-in-out;
> img:hover {
transform: scale(1.1);
}
.speed {
width: 16px;
height: 12px;
@@ -767,6 +794,12 @@
width: 240px;
height: 240px;
filter: drop-shadow(5px 5px 2.5px rgba(0, 0, 0, 0.35));
// transition: all 0.3s ease-in-out;
border-radius: 10px;
// &:hover {
// transform: scale(1.05);
// }
}
}
}
@@ -815,6 +848,10 @@
cursor: pointer;
transition: all 0.3s ease-in-out;
&:hover {
transform: scale(1.1);
}
&.img5 {
left: 0;
z-index: 2;
@@ -922,6 +959,10 @@
}
.operate {
transition: all 0.3s ease-in-out;
> img:hover {
transform: scale(1.1);
}
.cut {
width: 14px;
height: 12px;

View File

@@ -2,6 +2,7 @@
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
}
.container {
width: 100%;
@@ -299,51 +300,89 @@
border-radius: 18px;
}
.tag-item {
height: 60px;
line-height: 60px;
height: 66px;
border-radius: 12px;
background: #d5e7f7;
position: absolute;
font-size: 20px !important;
color: #1c3e5e;
padding: 0 25px;
width: fit-content;
cursor: pointer;
box-shadow: 0px 0 0 3px rgba(255, 255, 255, 0.223529);
background: rgba(255, 255, 255, 0.223529);
opacity: 1 !important;
padding: 3px;
}
.tag-item.show::after {
content: "";
width: 100%;
height: 100%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border-radius: 12px;
background: linear-gradient(var(--rotate), #db4743, #ffffff 43%, #c28846);
animation: bg 1.3s infinite linear;
}
@property --rotate {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
@keyframes bg {
0% {
--rotate: 0deg;
}
100% {
--rotate: 360deg;
}
}
.tag-item .tag-text {
background: #d5e7f7;
padding: 0 25px;
border-radius: 10px;
height: 100%;
display: flex;
align-items: center;
transition: background 0.3s, color 0.3s, z-index 0.3s, font-weight 0.3s;
position: relative;
z-index: 1;
}
.tag-item:hover {
font-weight: 650;
color: #583a05 !important;
background: #f19a04 !important;
z-index: 100 !important;
}
.tag-item:hover .tag-text {
background: #f19a04 !important;
}
.tag-item.item2 {
height: 50px;
line-height: 50px;
height: 56px;
color: #1c3e5e;
padding: 0 20px;
font-size: 18px !important;
}
.tag-item.item2 .tag-text {
padding: 0 20px;
background: #d5e7f7;
}
.tag-item.item3 {
height: 47px;
line-height: 47px;
height: 53px;
color: #1c3e5e;
padding: 0 16px;
font-size: 16px !important;
}
.tag-item.item3 .tag-text {
padding: 0 16px;
background: #d5e7f7;
}
.tag-item.item4 {
height: 30px;
line-height: 30px;
height: 36px;
color: #1c3e5e;
padding: 0 10px;
font-size: 14px !important;
}
.tag-item.item4 .tag-text {
padding: 0 10px;
background: #d5e7f7;
}
.tag-item.red {
.tag-item.red .tag-text {
color: #62263c !important;
background: linear-gradient(180deg, #ff8eba 0%, #f4458c 100%);
}

View File

@@ -2,6 +2,7 @@
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
}
.container {
@@ -355,70 +356,111 @@
}
.tag-item {
height: 60px;
line-height: 60px;
// border-radius: 30px;
height: 66px;
// line-height: 60px;
border-radius: 12px;
background: #d5e7f7;
// background: #d5e7f7;
position: absolute;
font-size: 20px !important;
color: #1c3e5e;
padding: 0 25px;
width: fit-content;
cursor: pointer;
box-shadow: 0px 0 0 3px rgba(255, 255, 255, 0.223529);
// box-shadow: 0px 0 0 3px rgba(255, 255, 255, 0.223529);
background: rgba(255, 255, 255, 0.223529);
opacity: 1 !important;
transition: background 0.3s, color 0.3s, z-index 0.3s, font-weight 0.3s;
// transition: background 0.3s, color 0.3s, z-index 0.3s, font-weight 0.3s;
padding: 3px;
&.show::after {
content: "";
width: 100%;
height: 100%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border-radius: 12px;
background: linear-gradient(var(--rotate), #db4743, #ffffff 43%, #c28846);
animation: bg 1.3s infinite linear;
}
@property --rotate {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
@keyframes bg {
0% {
--rotate: 0deg;
}
100% {
--rotate: 360deg;
}
}
.tag-text {
background: #d5e7f7;
padding: 0 25px;
border-radius: 10px;
height: 100%;
display: flex;
align-items: center;
transition: background 0.3s, color 0.3s, z-index 0.3s, font-weight 0.3s;
position: relative;
z-index: 1;
}
&:hover {
font-weight: 650;
color: #583a05 !important;
background: rgba(241, 154, 4, 1) !important;
z-index: 100 !important;
.tag-text {
background: rgba(241, 154, 4, 1) !important;
}
}
&.item2 {
height: 50px;
line-height: 50px;
// border-radius: 25px;
height: 56px;
color: #1c3e5e;
padding: 0 20px;
font-size: 18px !important;
background: #d5e7f7;
.tag-text {
padding: 0 20px;
background: #d5e7f7;
}
}
&.item3 {
height: 47px;
line-height: 47px;
// border-radius: 25px;
height: 53px;
color: #1c3e5e;
padding: 0 16px;
font-size: 16px !important;
background: #d5e7f7;
.tag-text {
padding: 0 16px;
background: #d5e7f7;
}
}
&.item4 {
height: 30px;
line-height: 30px;
// border-radius: 30px;
height: 36px;
color: #1c3e5e;
padding: 0 10px;
font-size: 14px !important;
background: #d5e7f7;
.tag-text {
padding: 0 10px;
background: #d5e7f7;
}
}
&.red {
color: #62263c !important;
background: linear-gradient(180deg, #ff8eba 0%, #f4458c 100%);
.tag-text {
color: #62263c !important;
background: linear-gradient(180deg, #ff8eba 0%, #f4458c 100%);
}
}
// &.red:hover {
// font-weight: 650;
// color: #583a05 !important;
// // background-color: rgba(241, 154, 4, 1) !important;
// background-color: rgb(255, 255, 255) !important;
// z-index: 100 !important;
// }
}
.bottom-play {

12
static/img/guess-bj-2.svg Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="360px" height="128px" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient gradientUnits="userSpaceOnUse" x1="181" y1="128" x2="292" y2="128" id="LinearGradient289">
<stop id="Stop290" stop-color="#9f2c39" offset="0" />
<stop id="Stop291" stop-color="#be3946" offset="1" />
</linearGradient>
</defs>
<g transform="matrix(1 0 0 1 -385 -1255 )">
<path d="M 151 128 L 0 97 L 347 0 L 360 128 L 151 128 Z " fill-rule="nonzero" fill="url(#LinearGradient289)" stroke="none" transform="matrix(1 0 0 1 385 1255 )" />
</g>
</svg>

12
static/img/guess-bj.svg Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="1064px" height="280px" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient gradientUnits="userSpaceOnUse" x1="115" y1="0" x2="1064" y2="280" id="LinearGradient295">
<stop id="Stop296" stop-color="#f3974a" offset="0" />
<stop id="Stop297" stop-color="#d73942" offset="1" />
</linearGradient>
</defs>
<g transform="matrix(1 0 0 1 -496 -1103 )">
<path d="M 184 280 L 0 237.125 L 104 0 L 1064 215.125 L 1064 262.5 C 1064 272.3 1055.2 280 1044 280 L 184 280 Z " fill-rule="nonzero" fill="url(#LinearGradient295)" stroke="none" transform="matrix(1 0 0 1 496 1103 )" />
</g>
</svg>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="298px" height="256px" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient gradientUnits="userSpaceOnUse" x1="271.334774788104" y1="21.570942662449" x2="0" y2="256" id="LinearGradient298">
<stop id="Stop299" stop-color="#c3454c" offset="0" />
<stop id="Stop300" stop-color="#eea058" offset="1" />
</linearGradient>
</defs>
<g transform="matrix(1 0 0 1 -424 -1125 )">
<path d="M 156.316964285714 253 C 154.321428571429 255 151.88244047619 256 149 256 C 146.11755952381 256 143.678571428571 255 141.683035714286 253 L 37.9151785714286 152.666666666667 C 36.8065476190476 151.777777777778 35.2821800595238 150.333333333333 33.3420758928571 148.333333333333 C 31.4019717261905 146.333333333333 28.3255208333333 142.694444444444 24.1127232142857 137.416666666667 C 19.8999255952381 132.138888888889 16.1305803571429 126.722222222222 12.8046875 121.166666666667 C 9.47879464285714 115.611111111111 6.5132068452381 108.888888888889 3.90792410714286 101 C 1.30264136904762 93.1111111111111 0 85.4444444444444 0 78 C 0 53.5555555555555 7.03980654761905 34.4444444444444 21.1194196428571 20.6666666666667 C 35.1990327380952 6.88888888888889 54.6555059523809 0 79.4888392857143 0 C 86.3623511904762 0 93.3744419642857 1.19444444444443 100.525111607143 3.58333333333334 C 107.67578125 5.9722222222222 114.327566964286 9.19444444444443 120.48046875 13.25 C 126.633370535714 17.3055555555555 131.927083333333 21.1111111111111 136.361607142857 24.6666666666667 C 140.796130952381 28.2222222222222 145.008928571429 32 149 36 C 152.991071428571 32 157.203869047619 28.2222222222222 161.638392857143 24.6666666666667 C 166.072916666667 21.1111111111111 171.366629464286 17.3055555555555 177.51953125 13.25 C 183.672433035714 9.19444444444443 190.32421875 5.9722222222222 197.474888392857 3.58333333333334 C 204.625558035714 1.19444444444443 211.637648809524 0 218.511160714286 0 C 243.344494047619 0 262.800967261905 6.88888888888889 276.880580357143 20.6666666666667 C 290.960193452381 34.4444444444444 298 53.5555555555555 298 78 C 298 102.555555555556 285.306175595238 127.555555555556 259.918526785714 153 L 156.316964285714 253 Z " fill-rule="nonzero" fill="url(#LinearGradient298)" stroke="none" transform="matrix(1 0 0 1 424 1125 )" />
</g>
</svg>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="173px" height="148px" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient gradientUnits="userSpaceOnUse" x1="45.5970992552194" y1="109.588769917092" x2="167.736885267016" y2="22.4597723935139" id="LinearGradient292">
<stop id="Stop293" stop-color="#c03c49" offset="0" />
<stop id="Stop294" stop-color="#eed680" offset="1" />
</linearGradient>
</defs>
<g transform="matrix(1 0 0 1 -351 -1223 )">
<path d="M 90.7477678571428 146.265625 C 89.5892857142857 147.421875 88.1733630952381 148 86.5 148 C 84.8266369047619 148 83.4107142857143 147.421875 82.2522321428571 146.265625 L 22.0111607142857 88.2604166666667 C 21.3675595238095 87.7465277777778 20.4826078869048 86.9114583333333 19.3563058035714 85.7552083333333 C 18.2300037202381 84.5989583333333 16.4440104166667 82.4952256944445 13.9983258928571 79.4440104166667 C 11.5526413690476 76.3927951388889 9.36439732142857 73.2612847222222 7.43359375 70.0494791666667 C 5.50279017857143 66.8376736111111 3.78115699404762 62.9513888888889 2.26869419642857 58.390625 C 0.756231398809524 53.8298611111111 0 49.3975694444444 0 45.09375 C 0 30.9618055555556 4.08686755952381 19.9131944444444 12.2606026785714 11.9479166666667 C 20.4343377976191 3.98263888888889 31.7295386904762 0 46.1462053571429 0 C 50.1365327380952 0 54.2073102678571 0.690538194444435 58.3585379464286 2.07161458333334 C 62.509765625 3.45269097222221 66.3713727678571 5.31553819444444 69.943359375 7.66015625 C 73.5153459821429 10.0047743055555 76.5885416666667 12.2048611111111 79.1629464285714 14.2604166666667 C 81.7373511904762 16.3159722222222 84.1830357142857 18.5 86.5 20.8125 C 88.8169642857143 18.5 91.2626488095238 16.3159722222222 93.8370535714286 14.2604166666667 C 96.4114583333333 12.2048611111111 99.4846540178572 10.0047743055555 103.056640625 7.66015625 C 106.628627232143 5.31553819444444 110.490234375 3.45269097222221 114.641462053571 2.07161458333334 C 118.792689732143 0.690538194444435 122.863467261905 0 126.853794642857 0 C 141.270461309524 0 152.565662202381 3.98263888888889 160.739397321429 11.9479166666667 C 168.913132440476 19.9131944444444 173 30.9618055555556 173 45.09375 C 173 59.2899305555556 165.630766369048 73.7430555555555 150.892299107143 88.453125 L 90.7477678571428 146.265625 Z " fill-rule="nonzero" fill="url(#LinearGradient292)" stroke="none" transform="matrix(1 0 0 1 351 1223 )" />
</g>
</svg>

18
static/img/guess-text.svg Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

1
static/js/ffmpeg.min.js vendored Normal file
View File

@@ -0,0 +1 @@
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FFmpegWASM=t():e.FFmpegWASM=t()}(self,()=>(()=>{"use strict";var i={m:{},d:(e,t)=>{for(var s in t)i.o(t,s)&&!i.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})},u:e=>e+".ffmpeg.js"};i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.g.importScripts&&(e=i.g.location+"");var e,t=i.g.document;if(!e&&t&&!(e=t.currentScript?t.currentScript.src:e)){var s=t.getElementsByTagName("script");if(s.length)for(var a=s.length-1;-1<a&&!e;)e=s[a--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),i.p=e,i.b=document.baseURI||self.location.href;var r,o,n,t={};i.r(t),i.d(t,{FFFSType:()=>o,FFmpeg:()=>c}),(n=r=r||{}).LOAD="LOAD",n.EXEC="EXEC",n.FFPROBE="FFPROBE",n.WRITE_FILE="WRITE_FILE",n.READ_FILE="READ_FILE",n.DELETE_FILE="DELETE_FILE",n.RENAME="RENAME",n.CREATE_DIR="CREATE_DIR",n.LIST_DIR="LIST_DIR",n.DELETE_DIR="DELETE_DIR",n.ERROR="ERROR",n.DOWNLOAD="DOWNLOAD",n.PROGRESS="PROGRESS",n.LOG="LOG",n.MOUNT="MOUNT",n.UNMOUNT="UNMOUNT";const E=(()=>{let e=0;return()=>e++})(),p=(new Error("unknown message type"),new Error("ffmpeg is not loaded, call `await ffmpeg.load()` first")),d=new Error("called FFmpeg.terminate()");new Error("failed to import ffmpeg-core.js");class c{#e=null;#t={};#s={};#r=[];#a=[];loaded=!1;#o=()=>{this.#e&&(this.#e.onmessage=({data:{id:e,type:t,data:s}})=>{switch(t){case r.LOAD:this.loaded=!0,this.#t[e](s);break;case r.MOUNT:case r.UNMOUNT:case r.EXEC:case r.FFPROBE:case r.WRITE_FILE:case r.READ_FILE:case r.DELETE_FILE:case r.RENAME:case r.CREATE_DIR:case r.LIST_DIR:case r.DELETE_DIR:this.#t[e](s);break;case r.LOG:this.#r.forEach(e=>e(s));break;case r.PROGRESS:this.#a.forEach(e=>e(s));break;case r.ERROR:this.#s[e](s)}delete this.#t[e],delete this.#s[e]})};#i=({type:i,data:a},r=[],o)=>this.#e?new Promise((e,t)=>{const s=E();this.#e&&this.#e.postMessage({id:s,type:i,data:a},r),this.#t[s]=e,this.#s[s]=t,o?.addEventListener("abort",()=>{t(new DOMException(`Message # ${s} was aborted`,"AbortError"))},{once:!0})}):Promise.reject(p);on(e,t){"log"===e?this.#r.push(t):"progress"===e&&this.#a.push(t)}off(e,t){"log"===e?this.#r=this.#r.filter(e=>e!==t):"progress"===e&&(this.#a=this.#a.filter(e=>e!==t))}load=({classWorkerURL:e,...t}={},{signal:s}={})=>(this.#e||(this.#e=e?new Worker(new URL(e,"file:///Users/focus/Projects/ffmpeg.wasm/packages/ffmpeg/dist/esm/classes.js"),{type:"module"}):new Worker(new URL(i.p+i.u(814),i.b),{type:void 0}),this.#o()),this.#i({type:r.LOAD,data:t},void 0,s));exec=(e,t=-1,{signal:s}={})=>this.#i({type:r.EXEC,data:{args:e,timeout:t}},void 0,s);ffprobe=(e,t=-1,{signal:s}={})=>this.#i({type:r.FFPROBE,data:{args:e,timeout:t}},void 0,s);terminate=()=>{for(const e of Object.keys(this.#s))this.#s[e](d),delete this.#s[e],delete this.#t[e];this.#e&&(this.#e.terminate(),this.#e=null,this.loaded=!1)};writeFile=(e,t,{signal:s}={})=>{const i=[];return t instanceof Uint8Array&&i.push(t.buffer),this.#i({type:r.WRITE_FILE,data:{path:e,data:t}},i,s)};mount=(e,t,s)=>this.#i({type:r.MOUNT,data:{fsType:e,options:t,mountPoint:s}},[]);unmount=e=>this.#i({type:r.UNMOUNT,data:{mountPoint:e}},[]);readFile=(e,t="binary",{signal:s}={})=>this.#i({type:r.READ_FILE,data:{path:e,encoding:t}},void 0,s);deleteFile=(e,{signal:t}={})=>this.#i({type:r.DELETE_FILE,data:{path:e}},void 0,t);rename=(e,t,{signal:s}={})=>this.#i({type:r.RENAME,data:{oldPath:e,newPath:t}},void 0,s);createDir=(e,{signal:t}={})=>this.#i({type:r.CREATE_DIR,data:{path:e}},void 0,t);listDir=(e,{signal:t}={})=>this.#i({type:r.LIST_DIR,data:{path:e}},void 0,t);deleteDir=(e,{signal:t}={})=>this.#i({type:r.DELETE_DIR,data:{path:e}},void 0,t)}return(n=o=o||{}).MEMFS="MEMFS",n.NODEFS="NODEFS",n.NODERAWFS="NODERAWFS",n.IDBFS="IDBFS",n.WORKERFS="WORKERFS",n.PROXYFS="PROXYFS",t})());

View File

@@ -1,5 +1,5 @@
const { createApp, ref, onMounted, nextTick, onUnmounted, computed } = Vue;
const search = createApp({
createApp({
setup() {
const musicData = ref([
["A组 世界在转动.MP3", "A组《来吧占领我的无私》.MP3"],
@@ -14,6 +14,11 @@ const search = createApp({
let isAnswer = ref(false);
onMounted(() => {
window.addEventListener("resize", () => {
// 重新计算 detailsHeight
const windowHeight = window.innerHeight;
detailsHeight.value = Math.max(windowHeight - 379 - 40, 350);
});
init();
// 获取可是窗口高度
@@ -74,8 +79,6 @@ const search = createApp({
let autoTimer = null;
const audioEnd = (item) => {
const nextItem = findNextItem(audiozSrc.value);
console.log("nextItem", nextItem);
if (nextItem) autoTimer = setTimeout(() => play(nextItem), 500);
audiozSrc.value = "";
};
@@ -144,18 +147,11 @@ const search = createApp({
let fluctuate = ref([]);
onMounted(() => {
// setInterval(() => {
// randomFluctuate();
// }, 150);
});
const randomFluctuate = () => {
fluctuate.value = []
fluctuate.value = [];
for (let i = 0; i < 30; i++) {
fluctuate.value.push(Math.floor(Math.random() * 10) + 1);
}
console.log("fluctuate", fluctuate.value);
};
return { fluctuate, isAnswer, detailsHeight, detailsRef, audioEnd, playSucceed, stop, audiozSrc, audioPlayer, backHome, select, loseState, winState, replyState, play, step, begin, musicData, nextStep };

File diff suppressed because one or more lines are too long

20
static/js/html2canvas.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
const { createApp, ref, onMounted, nextTick, onUnmounted, computed } = Vue;
const search = createApp({
const { createApp, ref, onMounted, nextTick, onUnmounted, computed, watch } = Vue;
createApp({
setup() {
const trait = [
{
@@ -118,10 +118,6 @@ const search = createApp({
bannerList.value = data.banner;
awardMVList.value = data.awardMVList;
data.awardAudioList.forEach((item, index) => {
item["playurl"] = `https://app.gter.net/image/miniApp/mp3/${index + 1}.mp3`;
});
awardAudioList.value = data.awardAudioList;
customList.value = data.customAudioList;
@@ -215,6 +211,8 @@ const search = createApp({
const src = playData.value?.playurl || "";
const area = playData.value?.area || "";
console.log(audioPlayer.value.src, src);
if (audioPlayer.value.src != src) {
manageAudio(src, area);
return;
@@ -235,7 +233,9 @@ const search = createApp({
// 管理音频播放
const manageAudio = (src, area) => {
const audio = audioPlayer.value;
closeAll();
setTimeout(() => {
if (audio?.src != src) audio.src = src;
audio.play().then(() => {
@@ -262,7 +262,7 @@ const search = createApp({
playData.value = { ...zeroOrderStudents.value, area };
}
});
}, 500);
}, 800);
};
// 重新播放
@@ -494,6 +494,11 @@ const search = createApp({
id = item.id;
}
if (area == "works") {
const item = awardAudioList.value[index];
id = item.id;
}
ajax("https://pujianchaoyin.com/api/getMusicDetail", {
id,
}).then((res) => {
@@ -508,9 +513,25 @@ const search = createApp({
customList.value[index] = { ...data, ...customList.value[index] };
manageAudio(data.playurl, area);
}
if (area == "works") {
awardAudioList.value[index] = { ...data, ...awardAudioList.value[index] };
manageAudio(data.playurl, area);
}
});
};
return { cutSong, getPlayUrl, handleBarDragBottomClick, startBarDragBottom, volumeShow, handleVolumeHide, handleVolumeShow, zeroOrderStudents, rePlay, playData, awardAudioList, changeInterval, awardMVList, bannerList, albumBoxRef, volume, handleVolumeClick, handleVolumeDrag, startDrag, stopDrag, volume, cutStudent, studentList, studentIndex, scrollToPrevious, scrollToNext, changePointer, pointerIndex, visibleRef, studentRef, customRef, formatTime, currentTimeFormatted, durationFormatted, worksRef, introduceRef, customList, closeAll, manageAudio, progress, closePreview, openPreview, previewState, audioPlayer, trait, fastForward };
const judgmentPlayUrl = (url, area, index) => {
if (url) manageAudio(url, area);
else getPlayUrl(index, area);
};
// 监听 previewState 如果为 true body.style.overflow = 'hidden'
watch(previewState, (newVal) => {
if (newVal) document.body.style.overflow = "hidden";
else document.body.style.overflow = "auto";
});
return { judgmentPlayUrl, cutSong, getPlayUrl, handleBarDragBottomClick, startBarDragBottom, volumeShow, handleVolumeHide, handleVolumeShow, zeroOrderStudents, rePlay, playData, awardAudioList, changeInterval, awardMVList, bannerList, albumBoxRef, volume, handleVolumeClick, handleVolumeDrag, startDrag, stopDrag, volume, cutStudent, studentList, studentIndex, scrollToPrevious, scrollToNext, changePointer, pointerIndex, visibleRef, studentRef, customRef, formatTime, currentTimeFormatted, durationFormatted, worksRef, introduceRef, customList, closeAll, manageAudio, progress, closePreview, openPreview, previewState, audioPlayer, trait, fastForward };
},
}).mount("#appIndex");

View File

@@ -1,5 +1,5 @@
const { createApp, ref, onMounted, nextTick, onUnmounted, computed } = Vue;
const search = createApp({
createApp({
setup() {
// 标签数据
let tags = ref([]);
@@ -16,412 +16,254 @@ const search = createApp({
return { containerWidth, containerHeight };
};
let bubbleContainer = null;
let bubbleContainerFill = null;
// 初始创建标签
const init = () => {
let tagsData = [
{
tag: "彩虹泡泡",
songs: [
{ name: "彩虹的微笑", path: "/music/rainbow_smile.mp3" },
{ name: "泡泡飞舞", path: "/music/bubble_dance.mp3" },
{ name: "七彩梦境", path: "/music/colorful_dream.mp3" },
{ name: "泡泡糖世界", path: "/music/bubblegum_world.mp3" },
{ name: "彩虹之光", path: "/music/rainbow_light.mp3" },
],
name: "孤独角落的守望",
path: "孤独角落的守望.MP3",
tags: ["浪漫", "爱情", "悲伤的角落", "复古旋律", "流行"],
},
{
tag: "星际漫游",
songs: [
{ name: "银河漫步", path: "/music/galaxy_walk.mp3" },
{ name: "宇宙之旅", path: "/music/space_journey.mp3" },
{ name: "星际迷航", path: "/music/star_trek.mp3" },
{ name: "太空漫步", path: "/music/space_walk.mp3" },
{ name: "银河系边缘", path: "/music/galaxy_edge.mp3" },
{ name: "星际穿越", path: "/music/interstellar.mp3" },
],
name: "碎梦残爱",
path: "碎梦残爱.MP3",
tags: ["浪漫", "爱情", "悲伤的角落", "复古旋律", "流行"],
},
{
tag: "开心到飞起",
songs: [
{ name: "快乐飞翔", path: "/music/happy_flying.mp3" },
{ name: "笑到飞起", path: "/music/laugh_high.mp3" },
{ name: "开心每一天", path: "/music/happy_everyday.mp3" },
{ name: "飞向快乐", path: "/music/fly_to_happy.mp3" },
],
name: "心碎的声音",
path: "心碎的声音.MP3",
tags: ["浪漫", "爱情", "悲伤的角落", "复古旋律", "流行"],
},
{
tag: "甜蜜时光",
songs: [
{ name: "甜蜜约定", path: "/music/sweet_promise.mp3" },
{ name: "时光慢递", path: "/music/slow_time.mp3" },
{ name: "甜蜜回忆", path: "/music/sweet_memory.mp3" },
{ name: "蜜糖时光", path: "/music/honey_time.mp3" },
{ name: "温柔时刻", path: "/music/gentle_moment.mp3" },
{ name: "甜蜜陪伴", path: "/music/sweet_company.mp3" },
{ name: "幸福时光", path: "/music/happy_time.mp3" },
],
name: "夜尽破晓",
path: "夜尽破晓.MP3",
tags: ["浪漫", "爱情", "悲伤的角落", "梦幻", "自由鼓点", "赛博心跳", "自由摇摆", "微风轻轻吹"],
},
{
tag: "探险",
songs: [
{ name: "丛林探险", path: "/music/jungle_adventure.mp3" },
{ name: "未知旅程", path: "/music/unknown_journey.mp3" },
{ name: "探索新世界", path: "/music/explore_new_world.mp3" },
{ name: "勇往直前", path: "/music/brave_forward.mp3" },
{ name: "神秘岛屿", path: "/music/mystery_island.mp3" },
],
name: "秋江别",
path: "秋江别.mp3",
tags: ["浪漫", "爱情", "相思", "古风", "江湖", "悲伤的角落", "温柔女声"],
},
{
tag: "梦幻",
songs: [
{ name: "梦幻旋律", path: "/music/dream_melody.mp3" },
{ name: "幻想曲", path: "/music/fantasy.mp3" },
{ name: "梦中的世界", path: "/music/dream_world.mp3" },
{ name: "梦幻泡影", path: "/music/dream_bubble.mp3" },
],
name: "锁心劫",
path: "锁心劫.mp3",
tags: ["浪漫", "爱情", "相思", "古风", "江湖", "悲伤的角落", "温柔女声"],
},
{
tag: "幻想曲",
songs: [
{ name: "幻想交响曲", path: "/music/fantasy_symphony.mp3" },
{ name: "幻想即兴曲", path: "/music/fantasy_impromptu.mp3" },
{ name: "幻想变奏曲", path: "/music/fantasy_variations.mp3" },
{ name: "幻想小夜曲", path: "/music/fantasy_serenade.mp3" },
{ name: "幻想曲集", path: "/music/fantasy_collection.mp3" },
{ name: "幻想奏鸣曲", path: "/music/fantasy_sonata.mp3" },
],
name: "大提琴与钢琴",
path: "《大提琴与钢琴》纯音乐.m4a",
tags: ["浪漫", "温柔", "幻想曲", "梦幻", "纯音乐", "自由摇摆", "微风轻轻吹"],
},
{
tag: "自由摇摆",
songs: [
{ name: "自由舞动", path: "/music/free_dance.mp3" },
{ name: "摇摆节奏", path: "/music/swing_rhythm.mp3" },
{ name: "自由爵士", path: "/music/free_jazz.mp3" },
{ name: "摇摆人生", path: "/music/swing_life.mp3" },
{ name: "自由即兴", path: "/music/free_improvisation.mp3" },
],
name: "经典游戏怀旧关卡",
path: "《经典游戏怀旧关卡》纯音乐.mp3",
tags: ["幻想曲", "梦幻", "纯音乐", "节奏大师", "快乐节拍", "自由鼓点", "赛博心跳", "赛博空间"],
},
{
tag: "夏日狂欢",
songs: [
{ name: "夏日派对", path: "/music/summer_party.mp3" },
{ name: "阳光沙滩", path: "/music/sunny_beach.mp3" },
{ name: "海边狂欢", path: "/music/beach_carnival.mp3" },
{ name: "夏日冰饮", path: "/music/summer_drink.mp3" },
{ name: "热带风情", path: "/music/tropical_style.mp3" },
{ name: "夏夜星空", path: "/music/summer_night_sky.mp3" },
],
name: "灵动琴音点亮旅行Vlog之旅",
path: "《灵动琴音点亮旅行Vlog之旅》纯音乐.mp3",
tags: ["彩虹泡泡", "幻想曲", "梦幻", "纯音乐", "节奏大师", "快乐节拍", "自由鼓点", "赛博心跳", "赛博空间"],
},
{
tag: "微风轻轻吹",
songs: [
{ name: "微风拂面", path: "/music/breeze_face.mp3" },
{ name: "轻风细雨", path: "/music/gentle_rain.mp3" },
{ name: "风中絮语", path: "/music/wind_whisper.mp3" },
{ name: "微风山谷", path: "/music/breeze_valley.mp3" },
{ name: "风的私语", path: "/music/wind_secret.mp3" },
],
name: "品牌创新科技",
path: "《品牌创新科技》纯音乐.mp3",
tags: ["纯音乐", "节奏大师", "快乐节拍", "自由鼓点", "赛博心跳", "赛博空间"],
},
{
tag: "江湖",
songs: [
{ name: "侠客行", path: "/music/knight_journey.mp3" },
{ name: "刀剑如梦", path: "/music/sword_dream.mp3" },
{ name: "笑傲江湖", path: "/music/laugh_jianghu.mp3" },
{ name: "侠义情深", path: "/music/knight_love.mp3" },
{ name: "江湖夜雨", path: "/music/jianghu_night_rain.mp3" },
{ name: "沧海一声笑", path: "/music/sea_laugh.mp3" },
],
name: "琴音交织的青春动画恋曲",
path: "《琴音交织的青春动画恋曲》纯音乐.mp3",
tags: ["彩虹泡泡", "浪漫", "温柔", "幻想曲", "梦幻", "纯音乐", "自由摇摆", "微风轻轻吹", "阳光正好", "青草香"],
},
{
tag: "浪漫",
songs: [
{ name: "浪漫星空", path: "/music/romantic_sky.mp3" },
{ name: "浪漫时光", path: "/music/romantic_time.mp3" },
{ name: "浪漫邂逅", path: "/music/romantic_encounter.mp3" },
{ name: "浪漫旋律", path: "/music/romantic_melody.mp3" },
{ name: "浪漫之夜", path: "/music/romantic_night.mp3" },
],
name: "我的金属心跳",
path: "《我的金属心跳》.mp3",
tags: ["流行", "自由摇摆", "赛博心跳", "节奏大师", "摇滚"],
},
{
tag: "阳光正好",
songs: [
{ name: "阳光灿烂", path: "/music/sunshine_bright.mp3" },
{ name: "正好遇见你", path: "/music/just_meet_you.mp3" },
{ name: "阳光路上", path: "/music/sunshine_road.mp3" },
{ name: "温暖阳光", path: "/music/warm_sunshine.mp3" },
{ name: "阳光照进心里", path: "/music/sunshine_heart.mp3" },
],
name: "向前跑",
path: "《向前跑》.mp3",
tags: ["流行", "自由摇摆"],
},
{
tag: "青草香",
songs: [
{ name: "草原晨曲", path: "/music/grassland_morning.mp3" },
{ name: "青草地", path: "/music/grass_land.mp3" },
{ name: "草香四溢", path: "/music/grass_fragrance.mp3" },
{ name: "青草摇曳", path: "/music/grass_swing.mp3" },
{ name: "草原牧歌", path: "/music/grassland_song.mp3" },
],
name: "战斗氛围",
path: "《战斗氛围》纯音乐.m4a",
tags: ["纯音乐", "节奏大师", "快乐节拍", "自由鼓点", "赛博心跳", "赛博空间", "摇滚"],
},
{
tag: "赛博心跳",
songs: [
{ name: "电子脉冲", path: "/music/electronic_pulse.mp3" },
{ name: "数字心跳", path: "/music/digital_heartbeat.mp3" },
{ name: "机械律动", path: "/music/mechanical_rhythm.mp3" },
{ name: "电流涌动", path: "/music/current_surge.mp3" },
{ name: "赛博都市", path: "/music/cyber_city.mp3" },
{ name: "数据流", path: "/music/data_flow.mp3" },
],
name: "长安三万里",
path: "《长安三万里》纯音乐.mp3",
tags: ["彩虹泡泡", "浪漫", "温柔", "幻想曲", "梦幻", "纯音乐", "星际漫游", "自由摇摆", "微风轻轻吹", "古风", "青草香", "阳光正好"],
},
{
tag: "赛博空间",
songs: [
{ name: "虚拟现实", path: "/music/virtual_reality.mp3" },
{ name: "网络漫游", path: "/music/network_roaming.mp3" },
{ name: "数据海洋", path: "/music/data_ocean.mp3" },
{ name: "赛博迷宫", path: "/music/cyber_maze.mp3" },
{ name: "电子宇宙", path: "/music/electronic_universe.mp3" },
],
name: "助眠",
path: "《助眠》纯音乐.mp3",
tags: ["彩虹泡泡", "浪漫", "温柔", "幻想曲", "梦幻", "纯音乐", "星际漫游"],
},
{
tag: "节奏大师",
songs: [
{ name: "节奏之王", path: "/music/rhythm_king.mp3" },
{ name: "鼓点狂欢", path: "/music/drum_carnival.mp3" },
{ name: "节奏游戏", path: "/music/rhythm_game.mp3" },
{ name: "律动人生", path: "/music/rhythm_life.mp3" },
{ name: "节奏与灵魂", path: "/music/rhythm_soul.mp3" },
],
name: "Compass Heart中文版",
path: "Compass Heart中文版.mp3",
tags: ["浪漫", "爱情", "相思", "流行", "悲伤的角落", "温柔女声", "自由鼓点"],
},
{
tag: "快乐节拍",
songs: [
{ name: "欢乐节拍", path: "/music/happy_beat.mp3" },
{ name: "快乐舞曲", path: "/music/happy_dance.mp3" },
{ name: "节拍欢歌", path: "/music/beat_song.mp3" },
{ name: "快乐音符", path: "/music/happy_note.mp3" },
{ name: "跳跃节奏", path: "/music/jumping_rhythm.mp3" },
],
name: "I Remember",
path: "I Remember.mp3",
tags: ["彩虹泡泡", "浪漫", "温柔", "幻想曲", "梦幻", "自由摇摆", "微风轻轻吹", "温柔女声", "青草香", "阳光正好"],
},
{
tag: "自由鼓点",
songs: [
{ name: "自由敲击", path: "/music/free_hit.mp3" },
{ name: "鼓点狂想", path: "/music/drum_fantasy.mp3" },
{ name: "自由节奏", path: "/music/free_rhythm.mp3" },
{ name: "鼓点即兴", path: "/music/drum_improvisation.mp3" },
{ name: "自由打击", path: "/music/free_percussion.mp3" },
],
name: "炒股的人不听慢歌",
path: "炒股的人不听慢歌.MP3",
tags: ["节奏大师", "快乐节拍", "自由鼓点", "赛博心跳", "赛博空间", "摇滚"],
},
{
tag: "悲伤的角落",
songs: [
{ name: "角落里的泪", path: "/music/corner_tears.mp3" },
{ name: "悲伤回忆", path: "/music/sad_memory.mp3" },
{ name: "孤独空间", path: "/music/lonely_space.mp3" },
{ name: "泪的痕迹", path: "/music/tear_trace.mp3" },
{ name: "心碎角落", path: "/music/heartbreak_corner.mp3" },
],
name: "成都真香故事",
path: "成都真香故事.mp3",
tags: ["生日祝福"],
},
{
tag: "一个人的狂欢",
songs: [
{ name: "独自狂欢", path: "/music/alone_carnival.mp3" },
{ name: "一人派对", path: "/music/one_person_party.mp3" },
{ name: "孤独欢乐", path: "/music/lonely_joy.mp3" },
{ name: "一个人的舞台", path: "/music/one_person_stage.mp3" },
{ name: "独自摇摆", path: "/music/alone_swing.mp3" },
],
name: "大闹天宫",
path: "大闹天宫.mp3",
tags: ["自由摇摆", "解压宣泄", "影视配乐", "在路上"],
},
{
tag: "经典金曲",
songs: [
{ name: "永恒经典", path: "/music/eternal_classic.mp3" },
{ name: "金曲回放", path: "/music/golden_replay.mp3" },
{ name: "不朽名曲", path: "/music/immortal_song.mp3" },
{ name: "经典重现", path: "/music/classic_reproduction.mp3" },
{ name: "金曲珍藏", path: "/music/golden_collection.mp3" },
{ name: "经典传承", path: "/music/classic_inheritance.mp3" },
],
name: "都市周末狂欢夜",
path: "都市周末狂欢夜.mp3",
tags: ["阳光正好", "自由摇摆", "摇滚", "解压宣泄", "派对聚会"],
},
{
tag: "民谣",
songs: [
{ name: "乡间小路", path: "/music/country_road.mp3" },
{ name: "吉他与诗", path: "/music/guitar_poem.mp3" },
{ name: "民谣故事", path: "/music/folk_story.mp3" },
{ name: "城市民谣", path: "/music/city_folk.mp3" },
{ name: "民谣之声", path: "/music/folk_voice.mp3" },
{ name: "木吉他旋律", path: "/music/acoustic_melody.mp3" },
],
name: "光耀华夏",
path: "光耀华夏.mp3",
tags: ["江湖", "影视配乐", "相思", "在路上", "流行金曲"],
},
{
tag: "摇滚",
songs: [
{ name: "摇滚精神", path: "/music/rock_spirit.mp3" },
{ name: "电吉他之声", path: "/music/electric_guitar.mp3" },
{ name: "摇滚革命", path: "/music/rock_revolution.mp3" },
{ name: "硬摇滚", path: "/music/hard_rock.mp3" },
{ name: "摇滚青春", path: "/music/rock_youth.mp3" },
{ name: "摇滚传奇", path: "/music/rock_legend.mp3" },
],
name: "广州",
path: "广州.mp3",
tags: ["浪漫", "在路上", "甜蜜时光"],
},
{
tag: "古风",
songs: [
{ name: "千年之约", path: "/music/thousand_year_promise.mp3" },
{ name: "墨香古韵", path: "/music/ink_ancient_rhyme.mp3" },
{ name: "青丝白发", path: "/music/black_white_hair.mp3" },
{ name: "琴瑟和鸣", path: "/music/instruments_harmony.mp3" },
{ name: "长安忆", path: "/music/changan_memory.mp3" },
{ name: "山水清音", path: "/music/landscape_sound.mp3" },
],
name: "蝴蝶与坦克",
path: "蝴蝶与坦克.mp3",
tags: ["星际漫游", "幻想曲", "赛博心跳", "赛博空间", "节奏大师", "快乐节拍", "自由鼓点"],
},
{
tag: "去旅行",
songs: [
{ name: "旅行的意义", path: "/music/travel_meaning.mp3" },
{ name: "背包客", path: "/music/backpacker.mp3" },
{ name: "远方的呼唤", path: "/music/distant_call.mp3" },
{ name: "旅途中", path: "/music/on_journey.mp3" },
{ name: "出发吧", path: "/music/lets_go.mp3" },
],
name: "加速心跳",
path: "加速心跳.mp3",
tags: ["幻想曲", "运动健身", "节奏大师", "快乐节拍"],
},
{
tag: "在路上",
songs: [
{ name: "公路之歌", path: "/music/highway_song.mp3" },
{ name: "一路向前", path: "/music/forward.mp3" },
{ name: "旅途风景", path: "/music/journey_scenery.mp3" },
{ name: "在路上", path: "/music/on_the_road.mp3" },
{ name: "行走的力量", path: "/music/walking_power.mp3" },
],
name: "脚步写下自由",
path: "脚步写下自由.mp3",
tags: ["开心到飞起", "微风轻轻吹", "解压宣泄", "通勤路上"],
},
{
tag: "学习BGM",
songs: [
{ name: "专注时刻", path: "/music/focus_moment.mp3" },
{ name: "学习氛围", path: "/music/study_atmosphere.mp3" },
{ name: "思考空间", path: "/music/thinking_space.mp3" },
{ name: "安静阅读", path: "/music/quiet_reading.mp3" },
{ name: "效率提升", path: "/music/efficiency_improvement.mp3" },
],
name: "经纬线",
path: "经纬线.mp3",
tags: ["温柔", "温柔女声", "民谣", "悲伤的角落", "助眠放松"],
},
{
tag: "运动健身",
songs: [
{ name: "热血沸腾", path: "/music/hot_blood.mp3" },
{ name: "健身节奏", path: "/music/fitness_rhythm.mp3" },
{ name: "运动激情", path: "/music/sports_passion.mp3" },
{ name: "跑步节拍", path: "/music/running_beat.mp3" },
{ name: "力量训练", path: "/music/strength_training.mp3" },
{ name: "健身房热曲", path: "/music/gym_hot_song.mp3" },
],
name: "旧唱片",
path: "旧唱片.mp3",
tags: ["爱情", "相思", "约会浪漫", "悲伤的角落"],
},
{
tag: "派对聚会",
songs: [
{ name: "派对之王", path: "/music/party_king.mp3" },
{ name: "聚会舞曲", path: "/music/party_dance.mp3" },
{ name: "欢乐时光", path: "/music/happy_time.mp3" },
{ name: "派对节奏", path: "/music/party_rhythm.mp3" },
{ name: "狂欢之夜", path: "/music/carnival_night.mp3" },
{ name: "聚会必备", path: "/music/party_essential.mp3" },
],
name: "快乐广场舞",
path: "快乐广场舞.mp3",
tags: ["复古旋律", "节奏大师", "快乐节拍"],
},
{
tag: "约会浪漫",
songs: [
{ name: "浪漫晚餐", path: "/music/romantic_dinner.mp3" },
{ name: "约会之夜", path: "/music/date_night.mp3" },
{ name: "烛光晚餐", path: "/music/candle_dinner.mp3" },
{ name: "浪漫时刻", path: "/music/romantic_moment.mp3" },
{ name: "甜蜜约会", path: "/music/sweet_date.mp3" },
],
name: "梅雨季",
path: "梅雨季.mp3",
tags: ["浪漫", "爱情", "悲伤的角落", "民谣", "微风轻轻吹", "去旅行", "在路上", "学习BGM"],
},
{
tag: "旅行路上",
songs: [
{ name: "旅途风景", path: "/music/journey_scenery.mp3" },
{ name: "公路之歌", path: "/music/highway_song.mp3" },
{ name: "旅行日记", path: "/music/travel_diary.mp3" },
{ name: "异国风情", path: "/music/exotic_style.mp3" },
{ name: "旅途中的歌", path: "/music/song_on_journey.mp3" },
],
name: "人生的过客",
path: "人生的过客.mp3",
tags: ["民谣", "旅行路上", "微风轻轻吹", "在路上", "专注工作/学习"],
},
{
tag: "助眠放松",
songs: [
{ name: "深度睡眠", path: "/music/deep_sleep.mp3" },
{ name: "轻松入眠", path: "/music/easy_sleep.mp3" },
{ name: "安眠曲", path: "/music/lullaby.mp3" },
{ name: "夜晚静谧", path: "/music/night_quiet.mp3" },
{ name: "舒缓心灵", path: "/music/soothe_mind.mp3" },
],
name: "",
path: "殇.mp3",
tags: ["复古旋律", "相思", "江湖"],
},
{
tag: "专注工作/学习",
songs: [
{ name: "专注时刻", path: "/music/focus_moment.mp3" },
{ name: "高效工作", path: "/music/efficient_work.mp3" },
{ name: "思维空间", path: "/music/thinking_space.mp3" },
{ name: "学习氛围", path: "/music/study_atmosphere.mp3" },
{ name: "专注力提升", path: "/music/focus_improvement.mp3" },
],
name: "深夜咖啡馆",
path: "深夜咖啡馆.mp3",
tags: ["浪漫", "爱情", "相思", "悲伤的角落", "助眠放松", "通勤路上"],
},
{
tag: "通勤路上",
songs: [
{ name: "早晨通勤", path: "/music/morning_commute.mp3" },
{ name: "城市节奏", path: "/music/city_rhythm.mp3" },
{ name: "地铁之声", path: "/music/subway_sound.mp3" },
{ name: "公交旅程", path: "/music/bus_journey.mp3" },
{ name: "上下班音乐", path: "/music/commute_music.mp3" },
],
name: "世界在转动",
path: "世界在转动.mp3",
tags: ["温柔", "阳光正好", "解压宣泄", "甜蜜时光"],
},
{
tag: "解压宣泄",
songs: [
{ name: "压力释放", path: "/music/pressure_release.mp3" },
{ name: "情绪宣泄", path: "/music/emotion_vent.mp3" },
{ name: "怒吼一声", path: "/music/roar.mp3" },
{ name: "释放自我", path: "/music/release_self.mp3" },
{ name: "压力消除", path: "/music/pressure_elimination.mp3" },
],
name: "她说",
path: "她说.mp3",
tags: ["悲伤的角落", "温柔女声", "青草香"],
},
{
tag: "生日祝福",
songs: [
{ name: "生日快乐", path: "/music/happy_birthday.mp3" },
{ name: "温馨祝福", path: "/music/warm_blessing.mp3" },
{ name: "生日派对", path: "/music/birthday_party.mp3" },
{ name: "祝福之歌", path: "/music/blessing_song.mp3" },
{ name: "幸福时刻", path: "/music/happy_moment.mp3" },
],
name: "天平行者",
path: "天平行者 .mp3",
tags: ["生日祝福"],
},
{
tag: "影视配乐",
songs: [
{ name: "电影主题", path: "/music/movie_theme.mp3" },
{ name: "剧情转折", path: "/music/plot_twist.mp3" },
{ name: "情感渲染", path: "/music/emotion_rendering.mp3" },
{ name: "史诗场景", path: "/music/epic_scene.mp3" },
{ name: "温情时刻", path: "/music/warm_moment.mp3" },
],
name: "跳楼机-上班版",
path: "跳楼机-上班版.MP3",
tags: ["专注工作/学习", "通勤路上", "解压宣泄"],
},
{
tag: "绘本音乐",
songs: [
{ name: "童话世界", path: "/music/fairy_tale_world.mp3" },
{ name: "绘本旋律", path: "/music/picture_book_melody.mp3" },
{ name: "想象空间", path: "/music/imagination_space.mp3" },
{ name: "童年回忆", path: "/music/childhood_memory.mp3" },
{ name: "故事音乐", path: "/music/story_music.mp3" },
],
name: "童年时光机",
path: "童年时光机.mp3",
tags: ["快乐节拍", "生日祝福", "绘本音乐"],
},
{
name: "无题",
path: "无题.mp3",
tags: ["节奏大师", "自由鼓点", "幻想曲", "纯音乐"],
},
{
name: "五星闪耀(青春)",
path: "五星闪耀(青春).mp3",
tags: ["专注工作/学习", "快乐节拍", "学习BGM"],
},
{
name: "吸烟区",
path: "吸烟区.mp3",
tags: ["通勤路上", "运动健身", "自由摇摆"],
},
{
name: "下一站旅行",
path: "下一站旅行.MP3",
tags: ["旅行路上", "微风轻轻吹"],
},
{
name: "尊重·成长·共赢",
path: "尊重·成长·共赢.mp3",
tags: ["派对聚会", "节奏大师"],
},
{
name: "Phantom in the Code",
path: "Phantom in the Code.mp3",
tags: ["彩虹泡泡", "温柔女声", "影视配乐"],
},
{
name: "We are family",
path: "We are family.MP3",
tags: ["通勤路上", "在路上", "派对聚会"],
},
{
name: "班味退散",
path: "班味退散.MP3",
tags: ["解压宣泄", "通勤路上", "开心到飞起", "自由摇摆"],
},
]; // 提取 tags 数组
// 执行转换
tagsData = transformMusicData(tagsData);
console.log(tagsData);
const redCount = Math.min(5, tagsData.length);
const redIndexes = [];
while (redIndexes.length < redCount) {
@@ -446,10 +288,13 @@ const search = createApp({
tagsFill.value = tagAll;
bubbleContainer?.[0]?.destroy();
bubbleContainerFill?.[0]?.destroy();
nextTick(() => {
const { containerWidth, containerHeight } = getContainerDimensions();
tagCloud({
bubbleContainerFill = tagCloud({
selector: "#bubbleContainerFill", // 元素选择器id 或 class
radius: [containerWidth / 2, containerHeight / 2], // 滚动横/纵轴半径, 默认60单位px取值60[60][60, 60]
mspeed: "normal", // 滚动最大速度, 取值: slow, normal(默认), fast
@@ -459,7 +304,7 @@ const search = createApp({
multicolour: false, // 彩色字体颜色随机取值true(默认),false
});
tagCloud({
bubbleContainer = tagCloud({
selector: "#bubbleContainer", // 元素选择器id 或 class
radius: [containerWidth / 2, containerHeight / 2],
mspeed: "normal",
@@ -471,6 +316,36 @@ const search = createApp({
});
};
const transformMusicData = (data) => {
// 使用Map存储标签和对应的歌曲
const tagMap = new Map();
// 遍历每首歌
data.forEach((song) => {
// 遍历当前歌曲的所有标签
song.tags.forEach((tag) => {
// 准备歌曲信息仅包含name和path
const songInfo = {
name: song.name,
path: song.path,
};
// 如果标签已存在于Map中添加歌曲否则创建新条目
if (tagMap.has(tag)) {
tagMap.get(tag).push(songInfo);
} else {
tagMap.set(tag, [songInfo]);
}
});
});
// 将Map转换为目标格式的数组
return Array.from(tagMap).map(([tag, songs]) => ({
tag,
songs,
}));
};
// 生成单次随机结果的函数
const getRandomOutcome = () => {
const random = Math.random(); // 生成0-1之间的随机数
@@ -488,6 +363,10 @@ const search = createApp({
onMounted(() => {
init();
window.addEventListener("resize", () => {
init();
});
// 添加进度更新事件监听器
if (audioPlayer.value) {
volume.value = audioPlayer.value.volume * 100;
@@ -512,9 +391,9 @@ const search = createApp({
const audioPlayer = ref(null);
const clickSongs = (songs) => {
const clickSongs = (tag, songs) => {
const randomIndex = Math.floor(Math.random() * songs.length);
const item = songs[randomIndex];
const item = { ...songs[randomIndex], tag };
manageAudio(item);
};
@@ -523,11 +402,10 @@ const search = createApp({
const audio = audioPlayer.value;
closeAll();
setTimeout(() => {
console.log("item", item);
if (audio?.src != item.path) audio.src = item.path;
audio.src = "https://app.gter.net/image/miniApp/mp3/1.mp3";
// audio.src = "/static/mp3/1.MP3";
if (audio?.src != item.path) audio.src = `./static/mp3/station/${item.path}`;
audio.play().then(() => (playData.value = { ...item, state: true }));
console.log("playData.value", playData.value);
}, 500);
};
@@ -638,25 +516,21 @@ const search = createApp({
durationFormatted.value = formatTime(duration);
};
// 快进 和 后退 10秒
// 切换下一首 或 上一首
const fastForward = (type = "fast") => {
if (!audioPlayer.value) return;
console.log("playData.value", playData.value);
const src = playData.value?.path || "";
tags.value.forEach((item) => {
if (item.tag == playData.value.tag) {
const songs = item.songs || [];
const index = songs.findIndex((song) => song.name == playData.value.name);
// 通过下标 type = "fast" 为下一首 否则为上一首 并且需要轮回播放
const newIndex = type == "fast" ? (index + 1) % songs.length : (index - 1 + songs.length) % songs.length;
if (audioPlayer.value.src != src) {
manageAudio(playData.value);
return;
}
let currentTime = audioPlayer.value.currentTime || 0;
const duration = audioPlayer.value.duration || 0;
let newTime = 0;
if (type == "fast") newTime = Math.min(currentTime + 10, duration);
else newTime = Math.max(currentTime - 10, 0);
audioPlayer.value.currentTime = newTime;
getProgress();
const data = { ...songs[newIndex], tag: item.tag };
manageAudio(data);
}
});
};
// 关闭所有播放
@@ -704,7 +578,6 @@ const search = createApp({
// 获取音量进度条元素
const progressBar = document.querySelector(".bottom-play .bottom-middle .progress-bar");
if (!progressBar) return;
console.log("14111111111");
const rect = progressBar.getBoundingClientRect();

162
未命名 (4).html Normal file
View File

@@ -0,0 +1,162 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Chrome 原生 API 屏幕录制</title>
<style>
.control-panel { margin: 20px 0; }
button { padding: 8px 16px; margin-right: 10px; cursor: pointer; }
#preview { border: 1px solid #ccc; width: 800px; height: 450px; margin: 10px 0; }
.status { color: #666; margin: 10px 0; }
</style>
</head>
<body>
<div class="control-panel">
<button id="startBtn">开始录制</button>
<button id="pauseBtn" disabled>暂停录制</button>
<button id="resumeBtn" disabled>继续录制</button>
<button id="stopBtn" disabled>停止录制</button>
</div>
<div class="status" id="status">状态:未开始</div>
<video id="preview" autoplay muted></video>
<script>
// 核心变量
let mediaStream = null; // 屏幕捕获流
let mediaRecorder = null; // 录制器实例
let recordedChunks = []; // 录制的视频数据块
let isPaused = false; // 录制暂停状态
// DOM 元素
const startBtn = document.getElementById('startBtn');
const pauseBtn = document.getElementById('pauseBtn');
const resumeBtn = document.getElementById('resumeBtn');
const stopBtn = document.getElementById('stopBtn');
const preview = document.getElementById('preview');
const status = document.getElementById('status');
// 1. 开始录制:捕获屏幕流 + 初始化录制器
startBtn.addEventListener('click', async () => {
try {
// 步骤1请求屏幕捕获权限用户选择录制范围全屏/窗口/标签页)
mediaStream = await navigator.mediaDevices.getDisplayMedia({
video: {
cursor: 'always', // 显示鼠标光标可选never/hidden
frameRate: { ideal: 30, max: 60 } // 录制帧率理想30帧最大60帧
},
audio: true // 同时捕获系统音频需浏览器支持Chrome需开启实验性功能
});
// 步骤2绑定流到预览窗口
preview.srcObject = mediaStream;
// 步骤3初始化 MediaRecorder指定录制格式为webmChrome 默认支持)
const options = {
mimeType: 'video/webm; codecs=vp9', // 推荐vp9编码体积小、画质好
// 可选:设置码率(根据需求调整,越高画质越好但体积越大)
// videoBitsPerSecond: 2500000 // 2.5Mbps
};
mediaRecorder = new MediaRecorder(mediaStream, options);
// 步骤4监听录制数据每块数据存入数组
mediaRecorder.ondataavailable = (e) => {
if (e.data.size > 0) {
recordedChunks.push(e.data);
}
};
// 步骤5监听录制结束自动下载视频
mediaRecorder.onstop = () => {
// 合并数据块为 Blob 视频文件
const blob = new Blob(recordedChunks, { type: 'video/webm' });
// 生成视频下载链接
const videoUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = videoUrl;
a.download = `录制视频_${new Date().getTime()}.webm`;
a.click();
// 释放资源
URL.revokeObjectURL(videoUrl);
recordedChunks = [];
// 重置状态
resetRecordingState();
status.textContent = '状态:录制已停止,视频已下载';
};
// 步骤6启动录制
mediaRecorder.start(1000); // 每1秒生成一个数据块可选
status.textContent = '状态:正在录制...';
// 更新按钮状态
startBtn.disabled = true;
pauseBtn.disabled = false;
stopBtn.disabled = false;
// 监听流结束(用户手动关闭捕获窗口)
mediaStream.getTracks().forEach(track => {
track.addEventListener('ended', () => {
if (mediaRecorder.state !== 'inactive') {
mediaRecorder.stop();
}
status.textContent = '状态:用户终止了屏幕捕获';
resetRecordingState();
});
});
} catch (error) {
console.error('录制启动失败:', error);
status.textContent = `状态:启动失败 - ${error.message}`;
resetRecordingState();
}
});
// 2. 暂停录制
pauseBtn.addEventListener('click', () => {
if (mediaRecorder.state === 'recording') {
mediaRecorder.pause();
isPaused = true;
status.textContent = '状态:录制已暂停';
pauseBtn.disabled = true;
resumeBtn.disabled = false;
}
});
// 3. 继续录制
resumeBtn.addEventListener('click', () => {
if (mediaRecorder.state === 'paused') {
mediaRecorder.resume();
isPaused = false;
status.textContent = '状态:正在录制...';
pauseBtn.disabled = false;
resumeBtn.disabled = true;
}
});
// 4. 停止录制
stopBtn.addEventListener('click', () => {
if (mediaRecorder.state !== 'inactive') {
// 停止录制器
mediaRecorder.stop();
// 停止所有流轨道(释放屏幕捕获)
mediaStream.getTracks().forEach(track => track.stop());
status.textContent = '状态:正在处理视频...';
}
});
// 辅助函数:重置录制状态
function resetRecordingState() {
mediaStream = null;
mediaRecorder = null;
isPaused = false;
preview.srcObject = null;
// 重置按钮
startBtn.disabled = false;
pauseBtn.disabled = true;
resumeBtn.disabled = true;
stopBtn.disabled = true;
}
</script>
</body>
</html>