Tone.js 序列进度与状态监控完整指南
发布时间 - 2026-01-29 00:00:00 点击率:次本文详解如何在 tone.js 中准确获取序列(sequence)的播放状态和进度,包括 `state` 和 `progress` 属性的真实行为、常见误区及可靠事件监听方案,助你精准触发完成回调。
在 Tone.js 中,Tone.Sequence 的 state 和 progress 属性常被开发者误用——它们并非实时反映当前播放位置或生命周期状态的通用指标,而是有特定语义和使用前提。
✅ 正确理解 state 与 progress
seq.state 是一个字符串,返回 "started"、"stopped" 或 "paused",仅在显式调用 .start()、.stop()、.pause() 后同步更新。它不会因音频时钟推进而自动刷新,且不表示“是否正在渲染音符”——例如,在 start(0) 后立即读取,可能仍为 "stopped"(因异步调度尚未生效)。
seq.progress 仅在启用循环(loop: true)时有意义:它返回 [0, 1) 区间内的归一化值,表示当前循环内已执行步数占比(如 4 步序列执行到第 2 步时为 0.5)。若 loop: false(默认),该值恒为 0,无法用于判断单次播放进度或是否完成。
因此,你示例中在回调内打印 seq.state 和 seq.progress 始终为 0,是完全符合设计预期的行为,并非 Bu

✅ 推荐方案:使用事件监听替代轮询
要可靠地检测序列完成(尤其是单次播放),应监听 ended 事件,而非依赖 progress:
const synth = new Tone.FMSynth().toDestination();
const notesArray = [
{ note: "B2", duration: "16n" },
{ note: "B3", duration: "16n" },
{ note: "A2", duration: "16n" },
{ note: "G2", duration: "16n" },
{ note: "B4", duration: "16n" }
];
const seq = new Tone.Sequence(
(time, note) => {
synth.triggerAttackRelease(note.note, note.duration, time, 0.1);
},
notesArray,
{
subdivisions: 1, // 每个数组元素对应 1 步(默认即 1)
loop: false // 明确禁用循环
}
).start(0);
// ✅ 正确:监听 ended 事件触发完成逻辑
seq.onended = () => {
console.log("✅ Sequence completed!");
// 在此处执行你的完成回调,如切换 UI、启动下一环节等
};
// ⚠️ 注意:Tone.js 14+ 中推荐使用 addEventListener 以兼容未来变更
// seq.addEventListener('ended', () => { ... });✅ 进阶:手动追踪进度(需自定义)
若需精确知道当前执行到第几步(如用于 UI 进度条),可结合 index 参数与 subdivisions 手动计数:
let currentStep = 0;
const totalSteps = notesArray.length;
const seq = new Tone.Sequence(
(time, note, index) => {
currentStep = index; // 0-based index of current callback invocation
synth.triggerAttackRelease(note.note, note.duration, time, 0.1);
console.log(`Playing step ${index + 1}/${totalSteps} → ${note.note}`);
if (index === totalSteps - 1) {
console.log("➡️ Final note triggered — sequence will end shortly.");
}
},
notesArray,
{ subdivisions: 1 }
).start(0);
seq.onended = () => {
console.log(`? Full sequence finished. Total steps: ${totalSteps}`);
currentStep = -1; // 重置
};⚠️ 注意事项总结
- ❌ 不要依赖 seq.progress 判断单次播放进度——它仅对循环序列有效;
- ❌ 避免在音符回调中直接读取 seq.state 判定播放中状态——它滞后且不可靠;
- ✅ 优先使用 onended 事件捕获完成时机;
- ✅ 如需步进控制,利用回调函数的 index 参数 + subdivisions 配置;
- ✅ 确保调用 Tone.start()(尤其在用户交互后)以解锁 Web Audio 上下文,否则序列可能静默失败。
通过以上方法,你将能稳健、精准地掌控 Tone.js 序列的生命周期与执行状态。
# js
# 回调函数
# 事件捕获
# red
# 字符串
# 循环
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
HTML5建模怎么导出为FBX格式_FBX格式兼容性及导出步骤【指南】
如何用狗爹虚拟主机快速搭建网站?
利用JavaScript实现拖拽改变元素大小
黑客入侵网站服务器的常见手法有哪些?
Laravel事件监听器怎么写_Laravel Event和Listener使用教程
网易LOFTER官网链接 老福特网页版登录地址
详解Nginx + Tomcat 反向代理 如何在高效的在一台服务器部署多个站点
laravel怎么用DB facade执行原生SQL查询_laravel DB facade原生SQL执行方法
如何快速搭建虚拟主机网站?新手必看指南
Laravel如何部署到服务器_线上部署Laravel项目的完整流程与步骤
Laravel如何使用.env文件管理环境变量?(最佳实践)
Laravel如何实现用户角色和权限系统_Laravel角色权限管理机制
Laravel怎么在Blade中安全地输出原始HTML内容
Win11搜索不到蓝牙耳机怎么办 Win11蓝牙驱动更新修复【详解】
Google浏览器为什么这么卡 Google浏览器提速优化设置步骤【方法】
Laravel安装步骤详细教程_Laravel环境搭建指南
Laravel数据库迁移怎么用_Laravel Migration管理数据库结构的正确姿势
网站制作大概要多少钱一个,做一个平台网站大概多少钱?
Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程
Laravel如何获取当前用户信息_Laravel Auth门面获取用户ID
UC浏览器如何设置启动页 UC浏览器启动页设置方法
JS碰撞运动实现方法详解
小米17系列还有一款新机?主打6.9英寸大直屏和旗舰级影像
教你用AI润色文章,让你的文字表达更专业
深圳网站制作平台,深圳市做网站好的公司有哪些?
专业商城网站制作公司有哪些,pi商城官网是哪个?
Laravel如何获取当前登录用户信息_Laravel Auth门面使用与Session用户读取【技巧】
html如何与html链接_实现多个HTML页面互相链接【互相】
香港服务器租用费用高吗?如何避免常见误区?
Laravel全局作用域是什么_Laravel Eloquent Global Scopes应用指南
如何实现建站之星域名转发设置?
Laravel Seeder怎么填充数据_Laravel数据库填充器的使用方法与技巧
Laravel Eloquent访问器与修改器是什么_Laravel Accessors & Mutators数据处理技巧
移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?
Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理
如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?
Laravel如何实现数据库事务?(DB Facade示例)
韩国代理服务器如何选?解析IP设置技巧与跨境访问优化指南
Laravel如何集成Inertia.js与Vue/React?(安装配置)
如何快速查询网址的建站时间与历史轨迹?
laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程
如何用花生壳三步快速搭建专属网站?
Laravel事件和监听器如何实现_Laravel Events & Listeners解耦应用的实战教程
Laravel怎么实现微信登录_Laravel Socialite第三方登录集成
Java Adapter 适配器模式(类适配器,对象适配器)优缺点对比
米侠浏览器网页背景异常怎么办 米侠显示修复
历史网站制作软件,华为如何找回被删除的网站?
Android中Textview和图片同行显示(文字超出用省略号,图片自动靠右边)
网站制作企业,网站的banner和导航栏是指什么?
Laravel任务队列怎么用_Laravel Queues异步处理任务提升应用性能

