<!DOCTYPE html>
<html>
<head>
<title>The VexFlow Tutorial</title>
<link href='http://fonts.googleapis.com/css?family=OFL+Sorts+Mill+Goudy+TT|Yanone+Kaffeesatz|Tangerine'
rel='stylesheet' type='text/css'>
<link href="../tabdiv/style.css" media="screen" rel="Stylesheet"
type="text/css" />
<!-- VexFlow Uncompiled Sources -->
<script src="../src/header.js"></script>
<script src="../src/vex.js"></script>
<script src="../src/flow.js"></script>
<script src="../src/tables.js"></script>
<script src="../src/fonts/vexflow_font.js"></script>
<script src="../src/glyph.js"></script>
<script src="../src/stave.js"></script>
<script src="../src/staveconnector.js"></script>
<script src="../src/tabstave.js"></script>
<script src="../src/tickcontext.js"></script>
<script src="../src/tickable.js"></script>
<script src="../src/note.js"></script>
<script src="../src/barnote.js"></script>
<script src="../src/ghostnote.js"></script>
<script src="../src/stavenote.js"></script>
<script src="../src/tabnote.js"></script>
<script src="../src/beam.js"></script>
<script src="../src/voice.js"></script>
<script src="../src/modifier.js"></script>
<script src="../src/modifiercontext.js"></script>
<script src="../src/accidental.js"></script>
<script src="../src/dot.js"></script>
<script src="../src/formatter.js"></script>
<script src="../src/stavetie.js"></script>
<script src="../src/tabtie.js"></script>
<script src="../src/tabslide.js"></script>
<script src="../src/bend.js"></script>
<script src="../src/vibrato.js"></script>
<script src="../src/annotation.js"></script>
<script src="../src/articulation.js"></script>
<script src="../src/tuning.js"></script>
<script src="../src/stavemodifier.js"></script>
<script src="../src/keysignature.js"></script>
<script src="../src/timesignature.js"></script>
<script src="../src/clef.js"></script>
<script src="../src/music.js"></script>
<script src="../src/keymanager.js"></script>
<script src="../src/renderer.js"></script>
<script src="../src/raphaelcontext.js"></script>
<script src="../src/stavevolta.js"></script>
<script src="../src/staverepetition.js"></script>
<script src="../src/stavebarline.js"></script>
<script src="../src/stavesection.js"></script>
<!-- VexFlow Compiled Source -->
<script src="../vexflow.js"></script>
<!-- Support Sources -->
<script src="../tabdiv/support/jquery.js"></script>
<script src="../tabdiv/support/raphael.js"></script>
<style type="text/css">
canvas {
background: #eed;
padding: 10px;
border: 10px solid #ddc;
}
div.egcode {
font-family: Courier;
font-size: 14px;
}
</style>
<script>
/* Take raw javascript code, and return moderately useful HTML */
function prettify_code(code) {
var lines = code.split(/\r\n|\n|\r/);
var new_lines = [];
for (var j = 0; j < lines.length; ++j) {
code = lines[j];
code = code.replace(/\s/g, " ");
code = code.replace(/>/g, ">");
code = code.replace(/</g, "<");
new_lines.push(code);
}
pretty_code = "<div class='egcode'>" + new_lines.join("<br/>") + "</div>";
return pretty_code;
}
/*
Find all the javascript examples and copy their source code
into the associated <code> blocks.
*/
$(function() {
$("div.description").each(function(index, sel) {
codes = $(sel).find("code.example");
codes.each(function(i, s) {
var example = $(s).attr("example");
var code = $($(sel).find(
"div.example." + example + " script")[0]).html();
$(s).html(prettify_code(code));
})
})
})
</script>
</head>
<body>
<div class="vex">
<a href="http://vexflow.com">VexFlow</a> |
<a href="http://vexflow.com/vextab">VexTab</a> |
<a href="http://vexflow.com/tabdiv">TabDiv</a> |
<a href="http://vexmachines.com">VexMachines</a> |
<a href="http://wickedmeanposters.com">Posters</a> |
<a href="http://0xfe.blogspot.com">0xfe</a>
</div>
<div class="header">
<h1>The VexFlow Tutorial</h1>
<div class="main">
<b>An n-step guide to programming with VexFlow</b>
</div>pre-pre-pre-alpha by <a href="http://0xfe.blogspot.com">0xfe</a>.
</div>
<div class="content">
<a href="http://vexflow.com">VexFlow</a> 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
<a href="http://en.wikipedia.org/wiki/Canvas_element">Canvas</a>
and
<a href="http://en.wikipedia.org/wiki/Scalable_Vector_Graphics">SVG</a>.
<p/>
It is important to note that VexFlow is a low-level rendering API;
most applications will want to use something like
<a href="http://vexflow.com/vextab">VexTab</a> which is a
higher-level language for rendering guitar tablature and music notation.
<p/>
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
<a href="http://raphaeljs.com">Raphael</a> JavaScript library into
your sources. That said, this tutorial also makes use of the jQuery
library to select and manipulate DOM elements.
<p/>
Finally, before we begin, this tutorial expects you to have some
experience with programming in JavaScript and working with music
notation.
<p/>
This source-code to this tutorial, including all the examples, is available
in the
<a href="http://github.com/0xfe/vexflow/blob/master/docs/tutorial.html">GitHub repository</a>.
Feel free to send your corrections, enhancements, or random rants to
<a href="http://0xfe.blogspot.com">0xFE</a>
/ <code class="example"><a href="http://twitter.com/11111110b">@11111110b</a></code>.
<p/>
Enjoy the show!
<h2>Step 1: The Basics</h2>
<div class="description one">
<p/>
Lets start with a quick example. Below, we have a canvas created with
the following code:
<p/>
<code class="html">
<canvas width=700 height=100"></canvas>
</code>
<p/>
Let's draw an empty treble stave on this canvas with VexFlow.
<br/>
<code class="example a" example="a"></code>
<br/>
Here's what it looks like.
<div class="example a" example="a">
<canvas width=525 height=120></canvas>
<p/>
<script>
var canvas = $("div.one div.a canvas")[0];
var renderer = new Vex.Flow.Renderer(canvas,
Vex.Flow.Renderer.Backends.CANVAS);
var ctx = renderer.getContext();
var stave = new Vex.Flow.Stave(10, 0, 500);
stave.addClef("treble").setContext(ctx).draw();
</script>
</div>
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.
<p/>
We then create a new <code>Vex.Flow.Stave</code> positioned at
<code>0, 0</code> with a width of <code>500</code> pixels.
<p/>
We pass the context to the stave and call <code>draw</code>, which
renders the stave on the context.
<p/>
Notice that the stave is not exactly drawn in position <code>0, 0</code>.
This is because it reserves some head-room for higher notes.
<p/>
</div>
<h2>Step 2: Add Some Notes</h2>
<div class="description two">
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.
<p/>
A <code>StaveNote</code> 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
<code>StaveNote</code> instances have an associated duration.
<p/>
These <code>StaveNote</code>s are grouped into a <code>Voice</code>.
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.
<p/>
Voices are grouped into <code>VoiceGroup</code>s. 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 <code>VoiceGroup</code> must contain at least one voice.
<p/>
Finally, you have a <code>Formatter</code>, 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.
<p/>
In the code below, we create a voice with two notes and a chord, and
render it on the stave.
<br/>
<code class="example a" example="a"></code>
<div class="example a" example="a">
<canvas width=525 height=120></canvas>
<p/>
<script>
var canvas = $("div.two div.a canvas")[0];
var renderer = new Vex.Flow.Renderer(canvas,
Vex.Flow.Renderer.Backends.CANVAS);
var ctx = renderer.getContext();
var stave = new Vex.Flow.Stave(10, 0, 500);
stave.addClef("treble").setContext(ctx).draw();
// Create the notes
var notes = [
// A quarter-note C.
new Vex.Flow.StaveNote({ keys: ["c/4"], duration: "q" }),
// A quarter-note D.
new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "q" }),
// A quarter-note rest. Note that the key (b/4) specifies the vertical
// position of the rest.
new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "qr" }),
// A C-Major chord.
new Vex.Flow.StaveNote({ keys: ["c/4", "e/4", "g/4"], duration: "q" })
];
// Create a voice in 4/4
var voice = new Vex.Flow.Voice({
num_beats: 4,
beat_value: 4,
resolution: Vex.Flow.RESOLUTION
});
// Add notes to voice
voice.addTickables(notes);
// Format and justify the notes to 500 pixels
var formatter = new Vex.Flow.Formatter().
joinVoices([voice]).format([voice], 500);
// Render voice
voice.draw(ctx, stave);
</script>
</div>
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.
<p/>
Lets add another voice to this tune.
<br/>
<code class="example b" example="b"></code>
<div class="example b" example="b">
<canvas width=525 height=120></canvas>
<p/>
<script>
var canvas = $("div.two div.b canvas")[0];
var renderer = new Vex.Flow.Renderer(canvas,
Vex.Flow.Renderer.Backends.CANVAS);
var ctx = renderer.getContext();
var stave = new Vex.Flow.Stave(10, 0, 500);
// Add a treble clef
stave.addClef("treble");
stave.setContext(ctx).draw();
// Create a quarter E, a half D, and a quarter C-Major chord.
var notes = [
new Vex.Flow.StaveNote({ keys: ["e/5"], duration: "q" }),
new Vex.Flow.StaveNote({ keys: ["d/5"], duration: "h" }),
new Vex.Flow.StaveNote({ keys: ["c/5", "e/5", "g/5"], duration: "q" })
];
// Create a second voice, with just one whole note
var notes2 = [
new Vex.Flow.StaveNote({ keys: ["c/4"], duration: "w" })
];
// Create a voice in 4/4
function create_4_4_voice() {
return new Vex.Flow.Voice({
num_beats: 4,
beat_value: 4,
resolution: Vex.Flow.RESOLUTION
});
}
// Create voices and add notes to each of them.
var voice = create_4_4_voice().addTickables(notes);
var voice2 = create_4_4_voice().addTickables(notes2);
// Format and justify the notes to 500 pixels
var formatter = new Vex.Flow.Formatter().
joinVoices([voice, voice2]).format([voice, voice2], 500);
// Render voice
voice.draw(ctx, stave);
voice2.draw(ctx, stave);
</script>
</div>
</div>
<h2>Step 3: All About Modifiers</h2>
<div class="description three">
<code>Modifier</code>s are essentially decorators that are
attached to notes. They
include <code>Accidental</code>s, <code>Vibrato</code>s,
<code>Dot</code>s, <code>Annotation</code>s etc.
<p/>
Modifiers for a single group of notes live inside a
<code>ModifierContext</code>. 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.
<p/>
Let's add some accidentals and dots.
<br/>
<code class="example a" example="a"></code>
<div class="example a" example="a">
<canvas width=525 height=120></canvas>
<p/>
<script>
var canvas = $("div.three div.a canvas")[0];
var renderer = new Vex.Flow.Renderer(canvas,
Vex.Flow.Renderer.Backends.CANVAS);
var ctx = renderer.getContext();
var stave = new Vex.Flow.Stave(10, 0, 500);
// Add a treble clef
stave.addClef("treble");
stave.setContext(ctx).draw();
var notes = [
// Dotted eighth E##
new Vex.Flow.StaveNote({ keys: ["e##/5"], duration: "8d" }).
addAccidental(0, new Vex.Flow.Accidental("##")).addDotToAll(),
// Sixteenth Eb
new Vex.Flow.StaveNote({ keys: ["eb/5"], duration: "16" }).
addAccidental(0, new Vex.Flow.Accidental("b")),
// Half D
new Vex.Flow.StaveNote({ keys: ["d/5"], duration: "h" }),
// Quarter Cm#5
new Vex.Flow.StaveNote({ keys: ["c/5", "eb/5", "g#/5"], duration: "q" }).
addAccidental(1, new Vex.Flow.Accidental("b")).
addAccidental(2, new Vex.Flow.Accidental("#"))
];
// Helper function to justify and draw a 4/4 voice
Vex.Flow.Formatter.FormatAndDraw(ctx, stave, notes);
</script>
</div>
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.
<p/>
This is by design, and exists for two reasons:
<ul>
<li>We don't want to couple rendering logic with notational logic.</li>
<li>
The API user has the final say for what should and should not be
displayed.
</li>
</ul>
<p/>
This enables higher level tools and libraries
(such as <a href="http://vexflow.com/vextab">VexTab</a>) to make rendering
decisions based on their own notational semantics.
<p/>
Also notice that we used the <code>FormatAndDraw</code> helper function
to create a 4/4 voice out of the notes, justify it to the stave, and
render all of it.
<p/>
Lets add a few more modifiers and see how they position themselves.
<br/>
<code class="example b" example="b"></code>
<div class="example b" example="b">
<canvas width=525 height=120></canvas>
<p/>
<script>
var canvas = $("div.three div.b canvas")[0];
var renderer = new Vex.Flow.Renderer(canvas,
Vex.Flow.Renderer.Backends.CANVAS);
var ctx = renderer.getContext();
var stave = new Vex.Flow.Stave(10, 0, 500);
// Add a treble clef
stave.addClef("treble");
stave.setContext(ctx).draw();
var notes = [
new Vex.Flow.StaveNote(
{ keys: ["g/4", "b/4", "cb/5", "e/5", "g#/5", "b/5"],
duration: "h" }).
addAccidental(0, new Vex.Flow.Accidental("bb")).
addAccidental(1, new Vex.Flow.Accidental("b")).
addAccidental(2, new Vex.Flow.Accidental("#")).
addAccidental(3, new Vex.Flow.Accidental("n")).
addAccidental(4, new Vex.Flow.Accidental("b")).
addAccidental(5, new Vex.Flow.Accidental("##")),
new Vex.Flow.StaveNote({ keys: ["c/4"], duration: "h" })
];
// Helper function to justify and draw a 4/4 voice
Vex.Flow.Formatter.FormatAndDraw(ctx, stave, notes);
</script>
</div>
Above, the accidentals are positioned such that they don't overlap but
maintain their X-relation to the associated note.
</div>
<h2>Step 3.5: An Interlude</h2>
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.
<p/>
Fortunately for you, there's a canonical location where this stuff
is kept.
<center>
<a href="https://github.com/0xfe/vexflow/blob/master/src/tables.js">
VexFlow Tables (vexflow/src/tables.js)
</a>
</center>
<p/>
The following tables are available:
<p/>
<ul>
<li>
<code>Vex.Flow.keyProperties.note_values</code> -
The list of valid note names.
</li>
<li>
<code>Vex.Flow.accidentalCodes.accidentals</code> -
The list of valid accidental names.
</li>
<li><code>Vex.Flow.keySignatures.keySpecs</code> -
The list of valid keys.</li>
<li><code>Vex.Flow.durationToTicks</code> -
The list of valid duration codes.</li>
</ul>
<h2>Step 4: Beams and Ties</h2>
<div class="description four">
VexFlow can beam your notes for you, but only if you ask it to. The
<code>Beam</code> 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.
<p/>
Let's create a melody.
<br/>
<code class="example a" example="a"></code>
<div class="example a" example="a">
<canvas width=525 height=120></canvas>
<p/>
<script>
var canvas = $("div.four div.a canvas")[0];
var renderer = new Vex.Flow.Renderer(canvas,
Vex.Flow.Renderer.Backends.CANVAS);
var ctx = renderer.getContext();
var stave = new Vex.Flow.Stave(10, 0, 500);
// Add a treble clef
stave.addClef("treble");
stave.setContext(ctx).draw();
var notes = [
new Vex.Flow.StaveNote({ keys: ["e##/5"], duration: "8d" }).
addAccidental(0, new Vex.Flow.Accidental("##")).addDotToAll(),
new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "16" }).
addAccidental(0, new Vex.Flow.Accidental("b"))
];
var notes2 = [
new Vex.Flow.StaveNote({ keys: ["c/4"], duration: "8" }),
new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "16" }),
new Vex.Flow.StaveNote({ keys: ["e/4"], duration: "16" }).
addAccidental(0, new Vex.Flow.Accidental("b"))
];
var notes3 = [
new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "16" }),
new Vex.Flow.StaveNote({ keys: ["e/4"], duration: "16" }).
addAccidental(0, new Vex.Flow.Accidental("#")),
new Vex.Flow.StaveNote({ keys: ["g/4"], duration: "32" }),
new Vex.Flow.StaveNote({ keys: ["a/4"], duration: "32" }),
new Vex.Flow.StaveNote({ keys: ["g/4"], duration: "16" })
];
var notes4 = [ new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "q" }) ];
// Create the beams
var beam = new Vex.Flow.Beam(notes);
var beam2 = new Vex.Flow.Beam(notes2);
var beam3 = new Vex.Flow.Beam(notes3);
var all_notes = notes.concat(notes2).concat(notes3).concat(notes4);
// Helper function to justify and draw a 4/4 voice
Vex.Flow.Formatter.FormatAndDraw(ctx, stave, all_notes);
// Render beams
beam.setContext(ctx).draw();
beam2.setContext(ctx).draw();
beam3.setContext(ctx).draw();
</script>
</div>
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.
<p/>
<code>Tie</code>ing notes involves a similar set of operations. To render
a tie, you create a <code>StaveTie</code> instance, and pass it the
two <code>StaveNote</code>s to tie together. Since each
<code>StaveNote</code> can be a chord, you also need to pass in the
indices of the specific notes you want to tie.
<p/>
For example:
<br/>
<code class="example b" example="b"></code>
<div class="example b" example="b">
<canvas width=525 height=120></canvas>
<p/>
<script>
var canvas = $("div.four div.b canvas")[0];
var renderer = new Vex.Flow.Renderer(canvas,
Vex.Flow.Renderer.Backends.CANVAS);
var ctx = renderer.getContext();
var stave = new Vex.Flow.Stave(10, 0, 500);
// Add a treble clef
stave.addClef("treble");
stave.setContext(ctx).draw();
var notes = [
new Vex.Flow.StaveNote({ keys: ["e##/5"], duration: "8d" }).
addAccidental(0, new Vex.Flow.Accidental("##")).addDotToAll(),
new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "16" }).
addAccidental(0, new Vex.Flow.Accidental("b"))
];
var notes2 = [
new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "8" }),
new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "16" }),
new Vex.Flow.StaveNote({ keys: ["c/4", "e/4"], duration: "16" }).
addAccidental(0, new Vex.Flow.Accidental("b"))
];
var notes3 = [
new Vex.Flow.StaveNote({ keys: ["c/4", "e/4"], duration: "8" }),
new Vex.Flow.StaveNote({ keys: ["e/4"], duration: "8" }).
addAccidental(0, new Vex.Flow.Accidental("#"))
];
var notes4 = [
new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "8" }),
new Vex.Flow.StaveNote({ keys: ["e/4"], duration: "8" }),
];
// Create the beams
var beam = new Vex.Flow.Beam(notes);
var beam2 = new Vex.Flow.Beam(notes2);
var beam3 = new Vex.Flow.Beam(notes3);
var beam4 = new Vex.Flow.Beam(notes4);
// Create a tie between the last note of the first group and the
// first note of the last group.
var tie = new Vex.Flow.StaveTie({
first_note: notes[1],
last_note: notes2[0],
first_indices: [0],
last_indices: [0]
});
// Create another tie between the two chords in the tune
var tie2 = new Vex.Flow.StaveTie({
first_note: notes2[2],
last_note: notes3[0],
first_indices: [0, 1],
last_indices: [0, 1]
});
var all_notes = notes.concat(notes2).concat(notes3).concat(notes4);
// Helper function to justify and draw a 4/4 voice
Vex.Flow.Formatter.FormatAndDraw(ctx, stave, all_notes);
// Render beams
beam.setContext(ctx).draw();
beam2.setContext(ctx).draw();
beam3.setContext(ctx).draw();
beam4.setContext(ctx).draw();
// Render ties
tie.setContext(ctx).draw();
tie2.setContext(ctx).draw();
</script>
</div>
And there you have ties and beams!
</div>
<h2>Step 5: Guitar Tablature</h2>
<div class="description five">
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.
<p/>
Let's write some tab.
<br/>
<code class="example a" example="a"></code>
<div class="example a" example="a">
<canvas width=525 height=160></canvas>
<p/>
<script>
// Get the rendering context
var canvas = $("div.five div.a canvas")[0];
var renderer = new Vex.Flow.Renderer(canvas,
Vex.Flow.Renderer.Backends.CANVAS);
var ctx = renderer.getContext();
ctx.setFont("Arial", 10, "").setBackgroundFillStyle("#eed");
// Create and draw the tablature stave
var tabstave = new Vex.Flow.TabStave(10, 0, 500);
tabstave.addTabGlyph();
tabstave.setContext(ctx).draw();
// Create some notes
var notes = [
// A single note
new Vex.Flow.TabNote({
positions: [{str: 3, fret: 7}],
duration: "q"}),
// A chord with the note on the 3rd string bent
new Vex.Flow.TabNote({
positions: [{str: 2, fret: 10},
{str: 3, fret: 9}],
duration: "q"}).
addModifier(new Vex.Flow.Bend("Full"), 1),
// A single note with a harsh vibrato
new Vex.Flow.TabNote({
positions: [{str: 2, fret: 5}],
duration: "h"}).
addModifier(new Vex.Flow.Vibrato().setHarsh(true).setVibratoWidth(70), 0)
];
Vex.Flow.Formatter.FormatAndDraw(ctx, tabstave, notes);
</script>
</div>
Above, we replaced <code>Stave</code> with <code>TabStave</code> and
<code>StaveNote</code> with <code>TabNote</code>. We also added some
bend and vibrato modifiers.
<p/>
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 <code>clearRect</code>. A
custom <code>clearRect</code> is required to clear sections of the
canvas. This is not supported by SVG because it has no "clear" semantics.
</div>
<center>
<h2>Step N + 1: Coming soon</h2>
<p/>
<a href="http://0xfe.blogspot.com">The Blog</a><p/>
</center>
</div>
</body>
</html>