VexFlow | My VexFlow | VexTab | 0xfe

The VexFlow Tutorial

An n-step guide to programming with VexFlow
pre-pre-pre-alpha by 0xfe.
VexFlow is an engraving engine for music notation, and can be used as a rendering backend to various kinds of online music tools, libraries, and applications. It is designed to run on HTML5 Canvas and SVG.

It is important to note that VexFlow is a low-level rendering API; most applications will want to use something like VexTab which is a higher-level language for rendering guitar tablature and music notation.

VexFlow is written completely in JavaScript and when using it with HTML5 Canvas, requires no external libraries or dependencies. For SVG support, you will need to include the Raphael JavaScript library into your sources. That said, this tutorial also makes use of the jQuery library to select and manipulate DOM elements.

Finally, before we begin, this tutorial expects you to have some experience with programming in JavaScript and working with music notation.

This source-code to this tutorial, including all the examples, is available in the GitHub repository. Feel free to send your corrections, enhancements, or random rants to 0xFE / @11111110b.

Enjoy the show!

Step 1: The Basics

Lets start with a quick example. Below, we have a canvas created with the following code:

  <canvas width=700 height=100"></canvas>

Let's draw an empty treble stave on this canvas with VexFlow.

Here's what it looks like.

In the above code first create a rendering context from the canvas element. This rendering context gives VexFlow a consistent 2D drawing interface, which is modeled on HTML5 Canvas.

We then create a new Vex.Flow.Stave positioned at 0, 0 with a width of 500 pixels.

We pass the context to the stave and call draw, which renders the stave on the context.

Notice that the stave is not exactly drawn in position 0, 0. This is because it reserves some head-room for higher notes.

Step 2: Add Some Notes

Adding notes to the stave is a slightly more involved process. To understand the code, you need to understand the data model of the renderer.

A StaveNote is a set of notes that belong on a stem. It can be a single note, or a chord. Its stem can be up, or down. All StaveNote instances have an associated duration.

These StaveNotes are grouped into a Voice. Voices have a time signature, and the set of notes in the voice (including the rests) must utilize all beats in the voice. So, a 4/4 voice with only three quarter-notes is invalid - you'll need to add another quarter note or rest.

Voices are grouped into VoiceGroups. This is particularly useful when you have multi-voice music. Upon rendering, the notes in each voice of the group aligned on the stave. A VoiceGroup must contain at least one voice.

Finally, you have a Formatter, which takes a voice group and justifies the voices based on configurable rules, so that all the voices in the group look pretty on the stave.

In the code below, we create a voice with two notes and a chord, and render it on the stave.

Notice how the notes are justified evenly on the stave based on the duration of each note? This is the formatter in action - keeping voices aligned, while balancing the spacing between the notes.

Lets add another voice to this tune.

Step 3: All About Modifiers

Modifiers are essentially decorators that are attached to notes. They include Accidentals, Vibratos, Dots, Annotations etc.

Modifiers for a single group of notes live inside a ModifierContext. This allows them to intelligently juxtapose themselves based on other modifiers in the context. For example, a chord consisting of two close-by notes, each having accidentals, needs to position the accidentals such that they don't clash.

Let's add some accidentals and dots.

In the above example, note that even though we set the note names and durations correctly, we explicitly request the rendering of accidentals and dots.

This is by design, and exists for two reasons:

This enables higher level tools and libraries (such as VexTab) to make rendering decisions based on their own notational semantics.

Also notice that we used the FormatAndDraw helper function to create a 4/4 voice out of the notes, justify it to the stave, and render all of it.

Lets add a few more modifiers and see how they position themselves.

Above, the accidentals are positioned such that they don't overlap but maintain their X-relation to the associated note.

Step 3.5: An Interlude

We've covered a bit of ground here, and you're probably asking for lists of valid note names, accidentals, durations, etc., that you can use with the API.

Fortunately for you, there's a canonical location where this stuff is kept.

VexFlow Tables (vexflow/src/tables.js)

The following tables are available:

Step 4: Beams and Ties

VexFlow can beam your notes for you, but only if you ask it to. The Beam class, when passed a set of contiguous notes (in a shared voice), is responsible for rendering beams based on the durations of each contained note.

Let's create a melody.

In the above example, we created three groups of notes with beams. The slope of the beams is a function of the direction of the music, and the number of beams for each group is dependent on the duration of the notes underneath.

Tieing notes involves a similar set of operations. To render a tie, you create a StaveTie instance, and pass it the two StaveNotes to tie together. Since each StaveNote can be a chord, you also need to pass in the indices of the specific notes you want to tie.

For example:

And there you have ties and beams!

Step 5: Guitar Tablature

VexFlow can also render guitar tablature. The mechanics for displaying tabs are the same as those for standard notation, except that you use different classes for staves and notes.

Let's write some tab.

Above, we replaced Stave with TabStave and StaveNote with TabNote. We also added some bend and vibrato modifiers.

There are two things we have to manually specify here -- the font style, and the background fill color. The former is used to display fret numbers, annotations, and other text. The latter is only required for the SVG backend (although using it with Canvas is harmless), and is used to create an internal implementation of clearRect. A custom clearRect is required to clear sections of the canvas. This is not supported by SVG because it has no "clear" semantics.

Step N + 1: More coming soon...

Meanwhile, go ahead and experiment in the Vexflow Sandbox.

The Blog