简介
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'),
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写文章(具体用法看另一篇文章)