Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Bottom aligned annotations #19

Merged
merged 3 commits into from

2 participants

@clinton

Hey 0xfe,

I just started using your VexFlow library and I am loving it. It is a great piece of work.

For my requirements it would be nice to have annotations under the stave, so I have added that feature. If you look at the test that I have added, you can see when this might be handy.

I hope you can use this feature in the main VexFlow branch. If you have any suggestions for me to fit your coding standard more closely, I will be happy to make the changes and submit to you again.

Thanks,

Clinton.

@0xfe
Owner

Hi Clinton,

Thanks very much for the commits. Bottom annotations are certainly a useful feature. I'll review them shortly and get back to you.

Mohit.

Clinton Forbes Got all tests to run in IE 9. (Added DOCTYPE and removed obsolete 'ce…
…nter' element which has been removed from HTML 5)
a42eacb
@clinton

Hey Mohit,
I also got the test suite to run in Internet Explorer 9. Only small changes.
Clinton.

@clinton
@0xfe
Owner

Yep, this is a bug and I will gladly accept a patch. The fix would be as follows:

  • Add a new key called "clef" to the "note_struct" constructor of StaveNote (stavenote.js)
  • Make Vex.Flow.keyProperties take "clef" as an optional parameter and return the correct line.
  • Add tests :-)

Let me know if you have any issues, Thanks.

@0xfe
Owner

LGTM. Thanks for the changes. I'll merge this.

@clinton
@clinton

Hi Mohit,

The fix for bass clef notes was dead simple following your notes. About five minutes work. Have added tests and all looks good.

I am guessing you are more into guitar than piano, correct?

See-ya,

Clinton.

@0xfe
Owner
@0xfe 0xfe merged commit 1bb1530 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 25, 2011
  1. Added ability to align annotations to underneath the stave

    Clinton Forbes authored
Commits on Jun 28, 2011
  1. Got all tests to run in IE 9. (Added DOCTYPE and removed obsolete 'ce…

    Clinton Forbes authored
    …nter' element which has been removed from HTML 5)
Commits on Jul 3, 2011
  1. Added support for bass clef notes

    Clinton Forbes authored
This page is out of date. Refresh to see the latest.
View
12 src/annotation.js
@@ -37,6 +37,10 @@ Vex.Flow.Annotation.prototype.setFont = function(family, size, weight) {
this.font = { family: family, size: size, weight: weight };
return this;
}
+Vex.Flow.Annotation.prototype.setBottom = function(bottom) {
+ this.bottom = bottom;
+ return this;
+}
Vex.Flow.Annotation.prototype.draw = function() {
if (!this.context) throw new Vex.RERR("NoContext",
@@ -46,8 +50,12 @@ Vex.Flow.Annotation.prototype.draw = function() {
var start = this.note.getModifierStartXY(Vex.Flow.Modifier.Position.LEFT,
this.index);
- var x = start.x - (this.getWidth() / 2) + 2;
- var y = this.note.getYForTopText(this.text_line) - 1;
+ var x = start.x - (this.getWidth() / 2) + 10;
+ if(this.bottom) {
+ var y = this.note.stave.getYForBottomText(this.text_line);
+ } else {
+ var y = this.note.getYForTopText(this.text_line) - 1;
+ }
this.context.save();
this.context.setFont(this.font.family, this.font.size, this.font.weight);
View
9 src/stave.js
@@ -23,7 +23,8 @@ Vex.Flow.Stave.prototype.init = function(x, y, width, options) {
spacing_between_lines_px: 10, // in pixels
space_above_staff_ln: 4, // in staff lines
space_below_staff_ln: 4, // in staff lines
- top_text_position: 1 // in staff lines
+ top_text_position: 1, // in staff lines
+ bottom_text_position: 7 // in staff lines
};
Vex.Merge(this.options, options);
@@ -83,6 +84,11 @@ Vex.Flow.Stave.prototype.getYForTopText = function(line) {
return this.getYForLine(-l - this.options.top_text_position);
}
+Vex.Flow.Stave.prototype.getYForBottomText = function(line) {
+ var l = line || 0;
+ return this.getYForLine(this.options.bottom_text_position + l);
+}
+
Vex.Flow.Stave.prototype.getYForNote = function(line) {
var options = this.options;
var spacing = options.spacing_between_lines_px;
@@ -96,6 +102,7 @@ Vex.Flow.Stave.prototype.getYForGlyphs = function() {
return this.getYForLine(3);
}
+
Vex.Flow.Stave.prototype.addGlyph = function(glyph) {
glyph.setStave(this);
this.glyphs.push(glyph);
View
3  src/stavenote.js
@@ -25,6 +25,7 @@ Vex.Flow.StaveNote.prototype.init = function(note_struct) {
superclass.init.call(this, note_struct.duration);
this.keys = note_struct.keys;
+ this.clef = note_struct.clef;
// Pull note rendering properties from duration.
this.glyph = Vex.Flow.durationToGlyph(this.duration);
@@ -44,7 +45,7 @@ Vex.Flow.StaveNote.prototype.init = function(note_struct) {
// All rests use the same position on the line.
// if (this.glyph.rest) key = this.glyph.position;
- var props = Vex.Flow.keyProperties(key);
+ var props = Vex.Flow.keyProperties(key, this.clef);
if (!props) {
throw new Vex.RuntimeError("BadArguments",
"Invalid key for note properties: " + key);
View
19 src/tables.js
@@ -10,7 +10,11 @@
Take a note in the format "Key/Octave" (e.g., "C/5") and return properties.
*/
-Vex.Flow.keyProperties = function(key) {
+Vex.Flow.keyProperties = function(key, clef) {
+ if(clef === undefined) {
+ clef = 'treble';
+ }
+
var pieces = key.split("/");
if (pieces.length != 2) {
@@ -26,6 +30,19 @@ Vex.Flow.keyProperties = function(key) {
var o = pieces[1];
var base_index = (o * 7) - (4 * 7);
var line = (base_index + value.index) / 2;
+
+ switch(clef){
+ case 'treble':
+ // no adjustment
+ break;
+ case 'bass':
+ line += 6;
+ break;
+ default:
+ throw new Vex.RERR("BadArguments",
+ "Unimplemented clef: " + clef);
+ }
+
var stroke = 0;
if (line <= 0 && (((line * 2) % 2) == 0)) stroke = 1; // stroke up
View
29 tests/annotation_tests.js
@@ -17,6 +17,8 @@ Vex.Flow.Test.Annotation.Start = function() {
Vex.Flow.Test.runTest("Fingerpicking", Vex.Flow.Test.Annotation.picking);
Vex.Flow.Test.runRaphaelTest("Fingerpicking (Raphael)",
Vex.Flow.Test.Annotation.picking);
+ Vex.Flow.Test.runTest("Bottom Annotation",
+ Vex.Flow.Test.Annotation.bottom);
}
Vex.Flow.Test.Annotation.simple = function(options, contextBuilder) {
@@ -131,3 +133,30 @@ Vex.Flow.Test.Annotation.picking = function(options, contextBuilder) {
Vex.Flow.Formatter.FormatAndDraw(ctx, stave, notes, 200);
ok(true, "Fingerpicking");
}
+
+Vex.Flow.Test.Annotation.bottom = function(options, contextBuilder) {
+ var ctx = contextBuilder(options.canvas_sel, 500, 240);
+ ctx.scale(1.5, 1.5); ctx.fillStyle = "#221"; ctx.strokeStyle = "#221";
+ var stave = new Vex.Flow.Stave(10, 10, 300).
+ addClef("treble").setContext(ctx).draw();
+
+ function newNote(note_struct) { return new Vex.Flow.StaveNote(note_struct); }
+ function newAnnotation(text) {
+ return (new Vex.Flow.Annotation(text)).setFont("Times",
+ Vex.Flow.Test.Font.size).setBottom(true); }
+
+ var notes = [
+ newNote({ keys: ["f/4"], duration: "w"}).
+ addAnnotation(0, newAnnotation("F")),
+ newNote({ keys: ["a/4"], duration: "w"}).
+ addAnnotation(0, newAnnotation("A")),
+ newNote({ keys: ["c/5"], duration: "w"}).
+ addAnnotation(0, newAnnotation("C")),
+ newNote({ keys: ["e/5"], duration: "w"}).
+ addAnnotation(0, newAnnotation("E"))
+ ];
+
+ Vex.Flow.Formatter.FormatAndDraw(ctx, stave, notes, 100);
+ ok(true, "Bottom Annotation");
+}
+
View
15 tests/flow.html
@@ -1,3 +1,4 @@
+<!DOCTYPE HTML>
<html>
<head>
@@ -166,16 +167,14 @@
</head>
<body>
- <center>
- <h1 id="qunit-header">VexFlow Tests</h1>
- <h2 id="qunit-banner"></h2>
- <h2 id="qunit-userAgent"></h2>
- <ol id="qunit-tests"></ol>
+ <h1 id="qunit-header">VexFlow Tests</h1>
+ <h2 id="qunit-banner"></h2>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
- <div id="vexflow_testoutput"></div>
+ <div id="vexflow_testoutput"></div>
- <p> Version 0.1 by <a href="http://0xfe.blogspot.com">0xfe</a> </p>
- </center>
+ <p> Version 0.1 by <a href="http://0xfe.blogspot.com">0xfe</a> </p>
</body>
</html>
View
44 tests/stavenote_tests.js
@@ -18,6 +18,9 @@ Vex.Flow.Test.StaveNote.Start = function() {
Vex.Flow.Test.runTest("Displacements", Vex.Flow.Test.StaveNote.displacements);
Vex.Flow.Test.runRaphaelTest("Displacements (Raphael)",
Vex.Flow.Test.StaveNote.displacements);
+ Vex.Flow.Test.runTest("StaveNote Draw - Bass", Vex.Flow.Test.StaveNote.drawBass);
+ Vex.Flow.Test.runRaphaelTest("StaveNote Draw - Bass(Raphael)",
+ Vex.Flow.Test.StaveNote.drawBass);
}
Vex.Flow.Test.StaveNote.ticks = function(options) {
@@ -131,6 +134,47 @@ Vex.Flow.Test.StaveNote.draw = function(options, contextBuilder) {
}
}
+Vex.Flow.Test.StaveNote.drawBass = function(options, contextBuilder) {
+ expect(36);
+ var ctx = new contextBuilder(options.canvas_sel, 600, 280);
+ var stave = new Vex.Flow.Stave(10, 10, 550);
+ var stave2 = new Vex.Flow.Stave(10, 150, 550);
+ stave.setContext(ctx);
+ stave.addClef('bass');
+ stave.draw();
+
+ var showNote = Vex.Flow.Test.StaveNote.showNote;
+ var notes = [
+ { clef: 'bass', keys: ["c/2", "e/2", "a/2"], duration: "w"},
+ { clef: 'bass', keys: ["c/3", "e/3", "a/3"], duration: "h"},
+ { clef: 'bass', keys: ["c/2", "e/2", "a/2"], duration: "q"},
+ { clef: 'bass', keys: ["c/3", "e/3", "a/3"], duration: "8"},
+ { clef: 'bass', keys: ["c/2", "e/2", "a/2"], duration: "16"},
+ { clef: 'bass', keys: ["c/3", "e/3", "a/3"], duration: "32"},
+ { clef: 'bass', keys: ["c/2", "e/2", "a/2"], duration: "h", stem_direction: -1},
+ { clef: 'bass', keys: ["c/2", "e/2", "a/2"], duration: "q", stem_direction: -1},
+ { clef: 'bass', keys: ["c/2", "e/2", "a/2"], duration: "8", stem_direction: -1},
+ { clef: 'bass', keys: ["c/2", "e/2", "a/2"], duration: "16", stem_direction: -1},
+ { clef: 'bass', keys: ["c/2", "e/2", "a/2"], duration: "32", stem_direction: -1},
+
+ { keys: ["b/4"], duration: "wr"},
+ { keys: ["b/4"], duration: "hr"},
+ { keys: ["b/4"], duration: "qr"},
+ { keys: ["b/4"], duration: "8r"},
+ { keys: ["b/4"], duration: "16r"},
+ { keys: ["b/4"], duration: "32r"},
+ { keys: ["x/4"], duration: "h"}
+ ];
+
+ for (var i = 0; i < notes.length; ++i) {
+ var note = notes[i];
+ var staveNote = showNote(note, stave, ctx, (i + 1) * 25);
+
+ ok(staveNote.getX() > 0, "Note " + i + " has X value");
+ ok(staveNote.getYs().length > 0, "Note " + i + " has Y values");
+ }
+}
+
Vex.Flow.Test.StaveNote.displacements = function(options, contextBuilder) {
expect(22);
var ctx = new contextBuilder(options.canvas_sel, 600, 140);
Something went wrong with that request. Please try again.