Astro音乐播放器

by 落墨in 技术

简介

Astro写文章的好处,就是简单,比如想在文章内加入一个音乐播放器,不用装插件,可以有几个方法实现:
先把音乐文件放到 public 目录,或者准备好外链地址:

public/
  music/
    song1.mp3

public/ 里的文件构建后会原样拷贝到站点根目录,能用固定 URL 直接引用。

方法一:原生 <audio>(推荐.md 直接用)

在 Astro 的 .md 文章里插音乐,最稳、零依赖的做法是直接写原生 HTML <audio> 标签——Markdown 默认允许内联 HTML 透传,不需要引任何库。

## 背景音乐
<audio controls src="/music/song1.mp3"></audio>

常用属性:

属性 作用 是否必须
controls 显示播放/暂停/进度条 必加
autoplay 自动播放(多数浏览器会拦截失效) 可选
loop 循环播放 可选
preload=“none” 不预加载,省流量 可选,列表多首时建议加

多格式兼容(浏览器不支持 mp3 时回退):

<audio controls>
  <source src="/music/song1.mp3" type="audio/mpeg">
  <source src="/music/song1.ogg" type="audio/ogg">
  你的浏览器不支持音频播放。
</audio>

注意:音乐文件放 public/ 而不是 src/assets/——后者会被 Astro 重命名为 hash 路径,不方便你手动写死 URL。

方法二:想更漂亮 / 想复用在多篇文章

一、使用mdx写文章,在任意位置插入播放器

.md 文件没法直接 import 组件。如果把文章后缀改成 .mdx(你的项目已经装了 @astrojs/mdx,直接可用),就能封装一个播放器组件:
新建文件:src/components/MusicPlayer.astro

---
const { src, title } = Astro.props;
---
<figure class="music">
  <figcaption>{title}</figcaption>
  <audio controls preload="none" src={src}></audio>
</figure>
<style>
  .music { margin: 1.5em 0; }
  .music audio { width: 100%; }
</style>

然后 .mdx 文章里写的时候插入:(具体用法看另一篇文章)

import MusicPlayer from '../components/MusicPlayer.astro'

<MusicPlayer src="/music/song1.mp3" title="我的歌" />

二、使用md写文章,在固定位置插入播放器

你的文章是 .md,而 .md 不能直接 import 组件,要先接进文章布局,frontmatter 驱动(推荐,不动文章后缀), 除了方法一里新建的文件外,还要再改两个文件:
1.src/content.config.ts — blog schema 加两行字段(放在 cover 附近):

music: z.string().optional(),
musicPos: z.enum(['top', 'end']).default('end'),
  1. src/layouts/BlogPost.astro 改三处:
### 引入import
import MusicPlayer from '../components/MusicPlayer.astro';
### (标题块 </div> 之后、hero 图之前)新增 top 位置渲染:
{Astro.props.music && Astro.props.musicPos === 'top' && (
  <MusicPlayer src={Astro.props.music} />
)}
### (<slot /> 之后、标签栏之前)新增 end 位置渲染:
{Astro.props.music && Astro.props.musicPos === 'end' && (
  <MusicPlayer src={Astro.props.music} />
)}

3.你的布局骨架(关键锚点)
BlogPost.astro 正文栏<div class="prose">内部,从上到下的顺序是:

<div class="prose">
  ┌─ <div class="title">  标题 + 日期 + <hr/>        ← 锚点A:标题区
  ├─ {heroImage && <figure>} 封面图                    ← 锚点B:封面之后
  ├─ <slot />                正文(Markdown 渲染处)
  ├─ <hr />
  ├─ {Astro.props.music && <MusicPlayer/>}   ← 锚点C:文章最后
  └─ <div class="post-footer"> 标签 + 回到顶部
</div>

此方式一个 music 字段只能渲染一次,位置是“全局统一”的,所有写了 music 的文章都在同一个位置(比如都放标题下)。它做不到「这篇放标题下、那篇放文末」。

4.用法(frontmatter)

想放的位置 frontmatter 写法
文末(默认,向后兼容) 只写 music: /music/x.wav(不写 musicPos)
标题下方 / hero 图之前 music: /music/x.wav + musicPos: top
显式文末 music: /music/x.wav + musicPos: end

musicPos 默认 end,frontmatter没写该字段,默认在文末;想要改到 top效果,改成 musicPos: top 即可。

这种方法适合,文章内只引用一个音乐播放,且固定位置,且只用.md写文章(具体用法看另一篇文章)