一、事件分类概览
事件类型分类
- 生命周期事件 - 实例创建、销毁
- 音频加载事件 - 音频文件加载过程
- 播放控制事件 - 播放、暂停、停止
- 时间进度事件 - 播放进度变化
- 交互事件 - 用户交互操作
- 音频处理事件 - 音频数据相关
- 插件事件 - 插件特有事件
- 错误事件 - 异常情况
二、事件列表(表格形式)
1. 生命周期事件
| 事件名称 | 触发时机 | 回调参数 | 示例 |
|---|
ready | 音频解码完成并准备就绪 | duration | wavesurfer.on('ready', (duration) => {}) |
destroy | 实例销毁时 | 无 | wavesurfer.on('destroy', () => {}) |
init | 初始化完成 | 无 | wavesurfer.on('init', () => {}) |
2. 音频加载事件
| 事件名称 | 触发时机 | 回调参数 | 示例 |
|---|
load | 开始加载音频时 | url | wavesurfer.on('load', (url) => {}) |
loading | 加载过程中 | percent | wavesurfer.on('loading', (percent) => {}) |
decode | 音频解码开始时 | 无 | wavesurfer.on('decode', () => {}) |
waveform-ready | 波形数据准备完成 | 无 | wavesurfer.on('waveform-ready', () => {}) |
audio-process | Web Audio API 处理音频时 | time | wavesurfer.on('audio-process', (time) => {}) |
3. 播放控制事件
| 事件名称 | 触发时机 | 回调参数 | 示例 |
|---|
play | 开始播放时 | 无 | wavesurfer.on('play', () => {}) |
pause | 暂停播放时 | 无 | wavesurfer.on('pause', () => {}) |
finish | 播放结束时 | 无 | wavesurfer.on('finish', () => {}) |
stop | 停止播放时 | 无 | wavesurfer.on('stop', () => {}) |
seek | 跳转到指定位置时 | progress | wavesurfer.on('seek', (progress) => {}) |
4. 时间进度事件
| 事件名称 | 触发时机 | 回调参数 | 示例 |
|---|
audioprocess | 播放过程中持续触发 | currentTime | wavesurfer.on('audioprocess', (time) => {}) |
timeupdate | 播放时间更新时 | currentTime | wavesurfer.on('timeupdate', (time) => {}) |
scroll | 波形滚动时 | scrollLeft | wavesurfer.on('scroll', (scroll) => {}) |
5. 交互事件
| 事件名称 | 触发时机 | 回调参数 | 示例 |
|---|
click | 点击波形图时 | relativeX, relativeY | wavesurfer.on('click', (x, y) => {}) |
dblclick | 双击波形图时 | relativeX, relativeY | wavesurfer.on('dblclick', (x, y) => {}) |
dragstart | 开始拖动时 | relativeX | wavesurfer.on('dragstart', (x) => {}) |
dragmove | 拖动过程中 | relativeX | wavesurfer.on('dragmove', (x) => {}) |
dragend | 拖动结束时 | relativeX | wavesurfer.on('dragend', (x) => {}) |
interaction | 任何交互发生时 | 无 | wavesurfer.on('interaction', () => {}) |
6. 音频处理事件
| 事件名称 | 触发时机 | 回调参数 | 示例 |
|---|
volume | 音量改变时 | volume | wavesurfer.on('volume', (vol) => {}) |
mute | 静音时 | muted | wavesurfer.on('mute', (isMuted) => {}) |
backend-change | 音频后端改变时 | backend | wavesurfer.on('backend-change', (backend) => {}) |
rate | 播放速率改变时 | rate | wavesurfer.on('rate', (rate) => {}) |
7. 错误事件
| 事件名称 | 触发时机 | 回调参数 | 示例 |
|---|
error | 发生错误时 | error | wavesurfer.on('error', (error) => {}) |
8. 区域插件事件 (Regions Plugin)
| 事件名称 | 触发时机 | 回调参数 | 示例 |
|---|
region-created | 区域创建时 | region | wavesurfer.on('region-created', (region) => {}) |
region-updated | 区域更新时 | region | wavesurfer.on('region-updated', (region) => {}) |
region-removed | 区域删除时 | region | wavesurfer.on('region-removed', (region) => {}) |
region-in | 播放进入区域时 | region | wavesurfer.on('region-in', (region) => {}) |
region-out | 播放离开区域时 | region | wavesurfer.on('region-out', (region) => {}) |
region-mouseenter | 鼠标进入区域时 | region, e | wavesurfer.on('region-mouseenter', (region, e) => {}) |
region-mouseleave | 鼠标离开区域时 | region, e | wavesurfer.on('region-mouseleave', (region, e) => {}) |
region-click | 点击区域时 | region, e | wavesurfer.on('region-click', (region, e) => {}) |
region-dblclick | 双击区域时 | region, e | wavesurfer.on('region-dblclick', (region, e) => {}) |
9. 标记插件事件 (Markers Plugin)
| 事件名称 | 触发时机 | 回调参数 | 示例 |
|---|
marker-created | 标记创建时 | marker | wavesurfer.on('marker-created', (marker) => {}) |
marker-updated | 标记更新时 | marker | wavesurfer.on('marker-updated', (marker) => {}) |
marker-removed | 标记删除时 | marker | wavesurfer.on('marker-removed', (marker) => {}) |
marker-click | 点击标记时 | marker, e | wavesurfer.on('marker-click', (marker, e) => {}) |
marker-drag | 拖动标记时 | marker, e | wavesurfer.on('marker-drag', (marker, e) => {}) |
10. 光标插件事件 (Cursor Plugin)
| 事件名称 | 触发时机 | 回调参数 | 示例 |
|---|
cursor-created | 光标创建时 | cursor | wavesurfer.on('cursor-created', (cursor) => {}) |
cursor-move | 光标移动时 | cursor, time | wavesurfer.on('cursor-move', (cursor, time) => {}) |
cursor-click | 点击光标时 | cursor, e | wavesurfer.on('cursor-click', (cursor, e) => {}) |
三、事件使用示例
1. 基本事件监听
const wavesurfer = WaveSurfer.create({
container: '#waveform',
waveColor: 'violet',
progressColor: 'purple'
});
wavesurfer.on('ready', function() {
console.log('音频准备就绪');
wavesurfer.play();
});
wavesurfer.on('play', () => console.log('开始播放'));
wavesurfer.on('pause', () => console.log('暂停播放'));
wavesurfer.on('finish', () => console.log('播放结束'));
wavesurfer.on('audioprocess', function(currentTime) {
console.log('当前时间:', currentTime.toFixed(2), '秒');
});
wavesurfer.on('error', function(error) {
console.error('发生错误:', error);
});
2. 一次性事件监听
wavesurfer.once('ready', function() {
console.log('音频第一次准备就绪');
});
await new Promise((resolve) => {
wavesurfer.once('ready', resolve);
});
3. 事件参数使用
wavesurfer.on('loading', function(percent) {
console.log(`加载进度: ${percent}%`);
document.getElementById('progress').style.width = percent + '%';
});
wavesurfer.on('seek', function(progress) {
console.log(`跳转到: ${(progress * 100).toFixed(1)}%`);
});
wavesurfer.on('volume', function(volume) {
console.log(`音量调整为: ${volume}`);
});
4. 区域事件处理
wavesurfer.on('region-created', function(region) {
console.log('区域创建:', region.id);
region.on('click', function() {
console.log('区域被点击:', region.id);
wavesurfer.play(region.start, region.end);
});
region.on('mouseenter', function() {
console.log('鼠标进入区域');
region.update({ color: 'rgba(255, 0, 0, 0.3)' });
});
region.on('mouseleave', function() {
console.log('鼠标离开区域');
region.update({ color: 'rgba(0, 0, 255, 0.3)' });
});
});
wavesurfer.on('region-in', function(region) {
console.log('进入区域:', region.id);
});
wavesurfer.on('region-out', function(region) {
console.log('离开区域:', region.id);
});
5. 交互事件处理
wavesurfer.on('click', function(relativeX, relativeY) {
const duration = wavesurfer.getDuration();
const currentTime = relativeX * duration;
console.log(`点击位置: X=${relativeX}, Y=${relativeY}`);
console.log(`对应时间: ${currentTime.toFixed(2)}秒`);
wavesurfer.seekTo(relativeX);
});
wavesurfer.on('dblclick', function(relativeX, relativeY) {
const time = relativeX * wavesurfer.getDuration();
wavesurfer.addMarker({
time: time,
color: 'red',
label: '标记点'
});
});
6. 自定义事件触发
wavesurfer.fireEvent('custom-event', { data: 'custom data' });
wavesurfer.on('custom-event', function(data) {
console.log('自定义事件触发:', data);
});
7. 事件移除
function handlePlay() {
console.log('播放中...');
}
wavesurfer.on('audioprocess', handlePlay);
wavesurfer.un('audioprocess', handlePlay);
wavesurfer.unAll('audioprocess');
wavesurfer.unAll();
四、事件生命周期流程图
音频加载过程事件流:
load → loading → decode → ready → waveform-ready
↓
error(如果发生错误)
播放过程事件流:
play → audioprocess(持续) → pause/stop/finish
↓
seek(跳转时)
↓
volume/rate(设置时)
交互事件流:
click/dblclick → dragstart → dragmove → dragend
↓
interaction
五、事件配置参数表格
事件相关配置参数
| 参数名 | 类型 | 默认值 | 说明 | 影响的事件 |
|---|
interact | Boolean | true | 是否启用交互 | click, dblclick, drag* |
dragToSeek | Boolean | true | 是否允许拖动跳转 | dragstart, dragmove, dragend |
autoScroll | Boolean | true | 播放时自动滚动 | scroll |
scrollParent | Boolean | false | 启用横向滚动 | scroll |
partialRender | Boolean | false | 部分渲染 | 影响渲染相关事件 |
splitChannels | Boolean | false | 分离声道显示 | 影响波形渲染事件 |
播放控制配置参数
| 参数名 | 类型 | 默认值 | 说明 | 影响的事件 |
|---|
audioRate | Number | 1 | 播放速度 | rate |
volume | Number | 1 | 音量 | volume, mute |
loopSelection | Boolean | true | 循环选区 | region-in, region-out |
backend | String | 'WebAudio' | 音频后端 | backend-change |
插件配置参数
| 插件 | 参数名 | 默认值 | 说明 | 影响的事件 |
|---|
| Regions | regions | [] | 初始区域 | region-* 事件 |
| Regions | dragSelection | true | 启用拖动选择 | region-created |
| Regions | maxRegions | null | 最大区域数 | 区域管理事件 |
| Markers | markers | [] | 初始标记 | marker-* 事件 |
| Markers | markerWidth | 2 | 标记宽度 | 标记渲染事件 |
| Cursor | showTime | true | 显示时间 | cursor-move |
| Cursor | followCursorY | false | 跟随光标Y轴 | cursor-move |
六、最佳实践
1. 事件监听顺序
wavesurfer.on('error', handleError);
wavesurfer.on('load', handleLoadStart);
wavesurfer.on('loading', updateProgress);
wavesurfer.on('ready', initializePlayer);
wavesurfer.on('play', updatePlayState);
wavesurfer.on('pause', updatePlayState);
wavesurfer.on('audioprocess', updateTime);
wavesurfer.on('finish', handlePlaybackEnd);
2. 内存管理
class AudioPlayer {
constructor() {
this.wavesurfer = WaveSurfer.create(config);
this.bindEvents();
}
bindEvents() {
this.eventHandlers = {
ready: this.handleReady.bind(this),
play: this.handlePlay.bind(this),
pause: this.handlePause.bind(this)
};
Object.entries(this.eventHandlers).forEach(([event, handler]) => {
this.wavesurfer.on(event, handler);
});
}
destroy() {
Object.entries(this.eventHandlers).forEach(([event, handler]) => {
this.wavesurfer.un(event, handler);
});
this.wavesurfer.destroy();
}
}
3. 事件防抖处理
let debounceTimer;
wavesurfer.on('audioprocess', (time) => {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
updateUI(time);
}, 100);
});
let lastUpdate = 0;
wavesurfer.on('scroll', (scrollLeft) => {
const now = Date.now();
if (now - lastUpdate > 200) {
lastUpdate = now;
updateScrollPosition(scrollLeft);
}
});
4. 错误处理
wavesurfer.on('error', (error) => {
console.error('WaveSurfer错误:', error);
if (error.message.includes('NetworkError')) {
showError('网络错误,请检查音频文件地址');
} else if (error.message.includes('decode')) {
showError('音频解码失败,请检查文件格式');
} else if (error.message.includes('NotSupportedError')) {
showError('浏览器不支持音频播放');
} else {
showError('音频播放错误: ' + error.message);
}
resetPlayerState();
});
七、事件调试技巧
1. 事件日志记录
function logAllEvents(wavesurfer) {
const events = [
'ready', 'load', 'loading', 'play', 'pause', 'finish',
'seek', 'audioprocess', 'error', 'volume', 'mute', 'rate',
'click', 'dblclick', 'dragstart', 'dragmove', 'dragend'
];
events.forEach(eventName => {
wavesurfer.on(eventName, (...args) => {
console.log(`[WaveSurfer Event] ${eventName}:`, args);
});
});
}
logAllEvents(wavesurfer);
2. 事件性能监控
const eventStats = {};
wavesurfer.on('audioprocess', () => {
const now = Date.now();
const key = 'audioprocess';
if (!eventStats[key]) {
eventStats[key] = { count: 0, lastTime: now };
}
eventStats[key].count++;
if (now - eventStats[key].lastTime >= 1000) {
console.log(`事件 ${key} 触发频率: ${eventStats[key].count}/秒`);
eventStats[key] = { count: 0, lastTime: now };
}
});
这是完整的事件文档涵盖了 WaveSurfer.js 的所有事件类型,包括核心事件和插件事件,提供了详细的使用示例和最佳实践,帮助你更好地理解和使用 WaveSurfer 的事件系统。