Vex.js — это мощная библиотека для работы с музыкальной нотацией и интерактивными партитурами в браузере. Одним из ключевых аспектов динамического взаимодействия с нотным редактором является отслеживание прогресса воспроизведения, что позволяет визуализировать текущую позицию в партитуре и синхронизировать события с аудио.
В Vex.js для воспроизведения нот используется объект
Vex.Flow.Player. Он работает с последовательностью нот
(Vex.Flow.StaveNote) и может запускать синтезированный звук
через Web Audio API. Каждая нота имеет собственную продолжительность, а
последовательность нот формирует ритмический поток.
Пример создания и воспроизведения простой последовательности нот:
const VF = Vex.Flow;
const notes = [
new VF.StaveNote({ keys: ["c/4"], duration: "q" }),
new VF.StaveNote({ keys: ["d/4"], duration: "q" }),
new VF.StaveNote({ keys: ["e/4"], duration: "q" }),
new VF.StaveNote({ keys: ["f/4"], duration: "q" })
];
const player = new VF.Player();
player.addSequence(notes);
player.start();
Этот код проигрывает четыре четвертные ноты последовательно. Но при таком подходе невозможно отслеживать, какая нота воспроизводится в данный момент.
Для мониторинга текущей позиции используется механизм
callback-функций. В Vex.js Player
предоставляет метод onNotePlayed, который вызывается каждый
раз, когда воспроизводится очередная нота.
Пример:
player.onNotePlayed((note, index) => {
console.log(`Играется нота: ${note.keys[0]}, индекс: ${index}`);
});
note — объект StaveNote, который
воспроизводится.index — порядковый номер ноты в
последовательности.С помощью этой информации можно реализовать подсветку нот на экране, синхронизацию с другими визуальными элементами или запись прогресса.
Для отображения прогресса часто используется подсветка текущей ноты в нотной линии. Для этого требуется изменить стиль ноты или добавить графический элемент поверх ноты:
function highlightNote(note, staveContext) {
const { x, y } = note.getAbsoluteXY();
staveContext.fillStyle = "red";
staveContext.beginPath();
staveContext.arc(x, y - 10, 5, 0, 2 * Math.PI);
staveContext.fill();
}
player.onNotePlayed((note) => {
highlightNote(note, context); // context — объект CanvasRenderingContext2D
});
Каждое срабатывание callback-функции позволяет мгновенно визуализировать текущую ноту, создавая эффект «следящего курсора» по партитуре.
Иногда требуется знать общее состояние воспроизведения в процентах. Для этого используется отношение индекса текущей ноты к общему числу нот:
player.onNotePlayed((note, index, sequenceLength) => {
const progress = ((index + 1) / sequenceLength) * 100;
console.log(`Прогресс: ${progress.toFixed(2)}%`);
});
Это позволяет строить прогресс-бары, таймеры или синхронизировать аудио с визуальными эффектами.
Vex.js работает с реальным временем воспроизведения, поэтому callback-функции могут быть использованы для синхронизации сторонних событий:
Пример запуска события на третьей ноте:
player.onNotePlayed((note, index) => {
if (index === 2) {
console.log("Третья нота достигнута — запускаем событие");
}
});
Vex.js позволяет поставить воспроизведение на паузу, перемотать к определенной ноте или останавливать его полностью. Это важно для интерактивных приложений:
player.pause(); // пауза
player.resume(); // продолжение
player.stop(); // полная остановка
player.seekTo(1); // перейти ко второй ноте (индекс 1)
Метод seekTo позволяет мгновенно перемещать прогресс
воспроизведения, что полезно для учебных целей или для повторного
проигрывания фрагментов.
В многонотных партитурах и аккордах важно учитывать:
В таких случаях Vex.js предоставляет объект Sequence с
точной временной шкалой, на которой каждая нота имеет метку
начала и конца. Это позволяет рассчитывать прогресс не по
количеству нот, а по времени:
const totalTime = player.sequence.getTotalDuration();
player.onNotePlayed((note) => {
const elapsed = player.sequence.getElapsedTime();
const progress = (elapsed / totalTime) * 100;
console.log(`Прогресс по времени: ${progress.toFixed(2)}%`);
});
Такой подход дает точную синхронизацию визуальных элементов с аудио и позволяет работать с сложными ритмическими структурами.
Эти подходы позволяют плавно отслеживать прогресс и обеспечивают высокую отзывчивость интерфейса даже на слабых устройствах.
Отслеживание прогресса воспроизведения в Vex.js становится центральной частью интерактивных музыкальных приложений. Используя callback-функции, визуализацию и расчёт прогресса по времени, можно строить динамичные, отзывчивые партитуры с точной синхронизацией звука и графики.