Визуализация музыкальной нотации (музыкального листа) в Javascript с VexFlow 2

У вас есть друзья, которые играют на музыкальных инструментах, и вы хотите получить удовольствие? Музыка состоит из множества символов, основными из которых являются персонал, ключи и ноты. Теоретически просто нарисовать эти символы, но очень сложно понять их и создать мелодию. Если вы веб-разработчик и вам нужно поработать в каком-нибудь музыкальном проекте, который должен отображать музыкальные записи в браузере, то сегодня ваш счастливый день, так как вам не нужно писать собственный сценарий для его достижения. Чтобы нарисовать ноты с помощью Javascript, мы рекомендуем вам использовать потрясающую Библиотека VexFlow.

VexFlow — это API-интерфейс рендеринга нотации музыки с открытым исходным кодом. Он полностью написан на JavaScript и работает прямо в браузере. VexFlow поддерживает HTML5 Canvas и SVG и работает во всех современных браузерах. VexFlow поддерживает стандартную музыку, табулатуру на гитаре и нотацию перкуссии. Хотя целью является поддержка подавляющего большинства западных музыкальных нотаций, VexFlow также поддерживает несколько альтернативных элементов, таких как микротональная нотация.

В этом уроке мы рассмотрим все основные задачи, которые вы можете выполнять с помощью библиотеки VexFlow в Javascript.

Требования

Как упоминалось ранее, мы собираемся использовать VexFlow 2 для достижения нашей цели создания удивительных музыкальных листов с использованием Javascript. Вы можете получить эту библиотеку, используя NPM, выполнив следующую команду в командной строке Node:

npm install vexflow

Или вы можете получить дистрибутив .js (отлаживать или же Минимизированный, релизы публикуются и обновляются автоматически в unpkg) в Официальный репозиторий в Github VexFlow здесь и включите его в свой документ с помощью тега script:

Эта библиотека с открытым исходным кодом выпущена под лицензией MIT.

Начиная

Как и в официальном руководстве VexFlow, мы ожидаем, что у вас будет некоторый опыт программирования на JavaScript и базовое понимание терминологии музыкальной нотации, в противном случае вы захотите плакать, пытаясь это осуществить.

Создание музыкального листа будет в основном основано на Staves. API VexFlow позволяет добавлять легкие посохи с некоторыми настраиваемыми параметрами:

Заметка

В большинстве наших примеров мы собираемся работать с SVG. Большинство сценариев, где масштабируемость является плюсом, будут лучше обслуживаться с использованием SVG, чем , Высокоточные сложные графики, такие как строительные и инженерные схемы, музыкальные листы, биологические диаграммы и т. Д. Являются примерами этого. Тем не менее, вы можете работать так, как хотите, поскольку VexFlow позволяет это.

1. Создание посоха с ключом и временем подписи

Ключ — это музыкальный символ, который указывает высоту написанных нот. Он расположен на одной из строк в начале нотного стана, он указывает название и высоту нот в этой строке. Только один ключ, который ссылается на примечание в пробеле, а не в строке, когда-либо использовался.

Чтобы добавить ключ и временную подпись, вам нужно сначала создать посох, куда вы хотите его поместить. Как мы уже говорили ранее, вы можете работать с VexFlow, используя canvas или SVG:

A. холст

Как сначала вам нужно создать canvas элемент с HTML, где будет работать Vex Flow:

Затем создайте новый экземпляр средства визуализации Vex Flow. Рендерер ожидает в качестве первого аргумента canvas элемент, который вы создали ранее, и в качестве второго параметра тип Canvas хранится как константа в VF.Renderer.Backends.CANVAS, Затем используйте метод изменения размера рендера, чтобы указать размеры элемента Canvas. Чтобы создать планку, вам понадобится контекст Canvas, с которым вы работаете, получить контекст из объекта рендерера (не с холста напрямую) с использованием getContext метод и сохранить его в переменной.

В качестве последнего шага создайте новый экземпляр класса VX Stave. Этот метод ожидает 3 аргумента, первый из которых будет целым числом, указывающим местоположение шеста на оси x холста, второй аргумент также является целым числом, указывающим местоположение шеста на оси y, а третий аргумент, тоже целое число, которое определяет ширину посоха. Из созданного объекта вы сможете вызвать addClef метод (который ожидает в качестве первого аргумента строку с типом ключа) и addTimeSignature (который ожидает в качестве первого аргумента идентификатор подписи времени, например 4/4, 4/2 и т. д.). Тогда используйте метод setContext который ожидает в качестве аргумента контекст объекта визуализации, ранее сохраненного в переменной, и из него выполняет draw метод рисования посоха.

VF = Vex.Flow;
// We created an object to store the information about the workspace
var WorkspaceInformation = {
// The  element in which you're going to work
canvas: document.getElementById("some-canvas-id"),
// Vex creates a canvas with specific dimensions
canvasWidth: 500,
canvasHeight: 500
};
// Create a renderer with Canvas
var renderer = new VF.Renderer(
WorkspaceInformation.canvas,
VF.Renderer.Backends.CANVAS
);
// Use the renderer to give the dimensions to the canvas
renderer.resize(WorkspaceInformation.canvasWidth, WorkspaceInformation.canvasHeight);
// Expose the context of the renderer
var context = renderer.getContext();
// And give some style to our canvas
context.setFont("Arial", 10, "").setBackgroundFillStyle("#eed");
/**
* Creating a new stave
*/
// Create a stave of width 400 at position x10, y40 on the canvas.
var stave = new VF.Stave(10, 40, 400);
// Add a clef and time signature.
stave.addClef("treble").addTimeSignature("4/4");
// Set the context of the stave our previous exposed context and execute the method draw !
stave.setContext(context).draw();

B. SVG

Как сначала вам нужно создать div элемент с HTML, где будет работать Vex Flow:


Затем создайте новый экземпляр средства визуализации Vex Flow. Рендерер ожидает в качестве первого аргумента div элемент, который вы создали ранее, и в качестве второго параметра тип SVG хранится как константа в VF.Renderer.Backends.SVG, Затем используйте метод изменения размера рендера, чтобы указать размеры элемента SVG. Чтобы создать планку, вам понадобится контекст SVG, с которым вы работаете, получить контекст из объекта рендерера, используя getContext метод и сохранить его в переменной.

В качестве последнего шага создайте новый экземпляр класса VX Stave. Этот метод ожидает 3 аргумента, первый из которых будет целым числом, указывающим местоположение шеста на оси x SVG, второй аргумент также является целым числом, указывающим местоположение шеста на оси y, а третий аргумент, тоже целое число, которое определяет ширину посоха. Из созданного объекта вы сможете вызвать addClef метод (который ожидает в качестве первого аргумента строку с типом ключа) и addTimeSignature (который ожидает в качестве первого аргумента идентификатор подписи времени, например 4/4, 4/2 и т. д.). Тогда используйте метод setContext который ожидает в качестве аргумента контекст объекта визуализации, ранее сохраненного в переменной, и из него выполняет draw метод рисования посоха.

VF = Vex.Flow;
// We created an object to store the information about the workspace
var WorkspaceInformation = {
// The div in which you're going to work
div: document.getElementById("some-div-id"),
// Vex creates a svg with specific dimensions
canvasWidth: 500,
canvasHeight: 500
};
// Create a renderer with SVG
var renderer = new VF.Renderer(
WorkspaceInformation.div,
VF.Renderer.Backends.SVG
);
// Use the renderer to give the dimensions to the SVG
renderer.resize(WorkspaceInformation.canvasWidth, WorkspaceInformation.canvasHeight);
// Expose the context of the renderer
var context = renderer.getContext();
// And give some style to our SVG
context.setFont("Arial", 10, "").setBackgroundFillStyle("#eed");
/**
* Creating a new stave
*/
// Create a stave of width 400 at position x10, y40 on the SVG.
var stave = new VF.Stave(10, 40, 400);
// Add a clef and time signature.
stave.addClef("treble").addTimeSignature("4/4");
// Set the context of the stave our previous exposed context and execute the method draw !
stave.setContext(context).draw();

Хотя на первый взгляд это кажется сложным, это не так, вам просто нужно набраться терпения, внимательно прочитать все примеры, попрактиковаться, и вы готовы к работе. Выполнение любого из предыдущего примера (SVG или Canvas) сгенерирует следующую посылку:

Пример Stave VexFlow

Вы захотите (и вам нужно) нарисовать много посохов (с различной информацией) в одном рабочем пространстве (SVG или Canvas), и вы можете легко добиться этого, если правильно обрабатываете значения местоположения. Проанализируйте следующий пример, чтобы увидеть, как визуализировать много посохов в одной рабочей области:


VF = Vex.Flow;
// Create an SVG renderer and attach it to the DIV element named "boo".
var div = document.getElementById("boo")
var renderer = new VF.Renderer(div, VF.Renderer.Backends.SVG);
var canvasDimensions = {
width: 820,
height: 300
};
// Configure the rendering context.
renderer.resize(canvasDimensions.width, canvasDimensions.height);
var context = renderer.getContext();
context.setFont("Arial", 10, "").setBackgroundFillStyle("#eed");
/**
* Left side staves
*/
// Create a stave of width 400 at position x10, y40 on the canvas.
var stave = new VF.Stave(10, 40, 400);
// Add a clef and time signature.
stave.addClef("treble").addTimeSignature("4/4");
// Connect it to the rendering context and draw!
stave.setContext(context).draw();
// Create a stave with soprano clef width 400 at position x10, y120 on the canvas.
var stave2 = new VF.Stave(10, 120, 400);
stave2.addClef("soprano").addTimeSignature("4/4");
stave2.setContext(context).draw();
/**
* Right side staves
*/
// Create a stave with baritone-f clef width 400 at position x420, y40 on the canvas.
var stave3 = new VF.Stave(420, 40, 400);
stave3.addClef("baritone-f").addTimeSignature("4/2");
stave3.setContext(context).draw();
// Create a stave with mezzo-soprano clef width 400 at position x420, y120 on the canvas without time signature
var stave4 = new VF.Stave(420, 120, 400);
stave4.addClef("mezzo-soprano");
stave4.setContext(context).draw();

Выполнение предыдущего скрипта, должно генерировать следующий контент на холсте:

Несколько посохов VexFlow Javascript

2. Написание заметок в нотный стан

StaveNote — это группа нотных нот, представляющих аккорд. Он может состоять из одной или нескольких нот, с или без стебля и флага. Последовательность нот представлена ​​тембром, и в VoiceGroup можно сгруппировать несколько голосов.

VF = Vex.Flow;
// We created an object to store the information about the workspace
var WorkspaceInformation = {
// The div in which you're going to work
div: document.getElementById("some-div-id"),
// Vex creates a svg with specific dimensions
canvasWidth: 500,
canvasHeight: 500
};
// Create a renderer with SVG
var renderer = new VF.Renderer(
WorkspaceInformation.div,
VF.Renderer.Backends.SVG
);
// Use the renderer to give the dimensions to the SVG
renderer.resize(WorkspaceInformation.canvasWidth, WorkspaceInformation.canvasHeight);
// Expose the context of the renderer
var context = renderer.getContext();
// And give some style to our SVG
context.setFont("Arial", 10, "").setBackgroundFillStyle("#eed");
/**
* Creating a new stave
*/
// Create a stave of width 400 at position x10, y40 on the SVG.
var stave = new VF.Stave(10, 40, 400);
// Add a clef and time signature.
stave.addClef("treble").addTimeSignature("4/4");
// Set the context of the stave our previous exposed context and execute the method draw !
stave.setContext(context).draw();
/**
* Draw notes
*/
var notes = [
// A quarter-note C.
new VF.StaveNote({clef: "treble", keys: ["c/4"], duration: "q" }),
// A quarter-note D.
new VF.StaveNote({clef: "treble", keys: ["d/4"], duration: "q" }),
// A quarter-note rest. Note that the key (b/4) specifies the vertical
// position of the rest.
new VF.StaveNote({clef: "treble", keys: ["b/4"], duration: "qr" }),
// A C-Major chord.
new VF.StaveNote({clef: "treble", keys: ["c/4", "e/4", "g/4"], duration: "q" })
];
// Create a voice in 4/4 and add above notes
var voice = new VF.Voice({num_beats: 4,  beat_value: 4});
voice.addTickables(notes);
// Format and justify the notes to 400 pixels.
var formatter = new VF.Formatter().joinVoices([voice]).format([voice], 400);
// Render voice
voice.draw(context, stave);

Выполнение предыдущего скрипта, должно генерировать следующий контент на холсте:

Заметки о Stave Vexflow

3. Создание гитарной табулатуры

Для гитар и других лаковых инструментов можно записать табулатуру вместо обычных нот. В этом случае знак TAB часто пишется вместо ключа. Количество строк нотного стана не обязательно пять: для каждой струны инструмента используется одна строка.

VF = Vex.Flow;
// Create an SVG renderer and attach it to the DIV element named "boo".
var div = document.getElementById("boo");
// Create a renderer that uses SVG
var renderer = new VF.Renderer(div, VF.Renderer.Backends.SVG);
// Configure the rendering context.
renderer.resize(500, 500);
var context = renderer.getContext();
// Create a tab stave of width 400 at position 10, 40 on the canvas.
var stave = new VF.TabStave(10, 40, 400);
stave.addClef("tab").setContext(context).draw();
var notes = [
// A single note
new VF.TabNote({
positions: [
{str: 3, fret: 7}
],
duration: "q"
}),
// A chord with the note on the 3rd string bent
new VF.TabNote({
positions: [
{str: 2, fret: 10},
{str: 3, fret: 9},
{str: 4, fret: 8},
],
duration: "q"
}).addModifier(
new VF.Bend("Full"), 1
),
// A single note with a harsh vibrato
new VF.TabNote({
positions: [{str: 2, fret: 5}],
duration: "h"
}).addModifier(
new VF.Vibrato().setHarsh(true).setVibratoWidth(50), 0
)
];
VF.Formatter.FormatAndDraw(context, stave, notes);

Выполнение предыдущего скрипта должно сгенерировать следующее:

Гитара Tab Vex Flow Javascript

Использование EasyScore

Если вы уже достигли этой точки статьи, то вы, вероятно, сказали себе «черт, это много кода», поэтому VexFlow предлагает утилиту, которая делает написание музыкальной нотации намного проще, например, EasyScore. EasyScore — это крошечный язык, который вы можете использовать для генерации всех элементов VexFlow, необходимых для последовательности музыкальной нотации. Язык поддерживает заметки, случайные числа, лучи, точки, кортежи и другие распространенные элементы обозначений.

Например, шаг 3 учебника по началу работы можно заменить на следующий код с помощью EasyScore:

// Create an SVG renderer and attach it to the DIV element named "boo".
var vf = new Vex.Flow.Factory({
renderer: {
selector: 'some-div-id'
}
});
var score = vf.EasyScore();
var system = vf.System();
system.addStave({
voices: [
score.voice(score.notes('C4/q, d4, b4/r, (C4 E4 G4)/q'))
]
}).addClef('treble').addTimeSignature('4/4');
vf.draw();

Это явно меньше кода и в некотором смысле легко читается, не так ли? Выполнение предыдущего кода даст тот же результат, что и на шаге 3:

Заметки о Stave Vexflow

EasyScore даже позволяет добавить еще одну нотку, которая воспроизводит еще два голоса:

// Create an SVG renderer and attach it to the DIV element named "boo".
var vf = new Vex.Flow.Factory({
renderer: {
selector: 'boo',
height: 800,
width: 800
}
});
var score = vf.EasyScore();
var system = vf.System();
system.addStave({
voices: [
score.voice(score.notes('C#5/q, B4, A4, G#4', {
stem: 'up'
})),
score.voice(score.notes('C#4/h, C#4', {
stem: 'down'
}))
]
}).addClef('treble').addTimeSignature('4/4');
system.addConnector();
system.addStave({
voices: [
score.voice(score.notes('C#3/q, B2, A2/8, B2, C#3, D3', {
clef: 'bass',
stem: 'up'
})),
score.voice(score.notes('C#2/h, C#2', {
clef: 'bass',
stem: 'down'
}))
]
}).addClef('bass').addTimeSignature('4/4');
vf.draw();

Который будет генерировать:

Несколько голосов EasyScore VexFlow

песочница

Если вы хотите попробовать VexFlow в Браузере, они предлагают скрипку, которая всегда использует самую последнюю сборку библиотеки, проверить это здесь. Наконец, мы поощряем чтение вики из VexFlow.

Ссылка на основную публикацию
Adblock
detector