Equal horizontal spacing between StaveNotes, GhostNotes, and Rests

451 views
Skip to first unread message

danielr...@gmail.com

unread,
Sep 15, 2016, 4:30:18 AM9/15/16
to vexflow
I'm currently working on a project that requires a horizontal grid, in which all of the quarter note StaveNotes, GhostNotes, and Rests fill the same horizontal space.  I tried to achieve a horizontal space of 40 pixels for each element in a voice by using the following...
let formatter = new Vex.Flow.Formatter().format([hoverVoice], (40 * this.hoverNote.length));

However, this just determines the average space per element.  When there are StaveNotes, GhostNotes, and Rests in the voice StaveNotes take up more than 40 pixels and GhostNotes and Rests take up less than 40 pixels.  Does anyone have any clues on how to make sure that each 1 beat element will take up the exact same horizontal space in a voice?

Mohit Muthanna Cheppudira

unread,
Sep 15, 2016, 12:22:43 PM9/15/16
to vexflow
It's probably simpler if you don't use the formatter for this and position then notes manually (using TickContext.setX). E.g., this is how `Formatter.SimpleFormat` places notes for tests without using the main formatter:

static SimpleFormat(notes, x = 0, { paddingBetween = 10 } = {}) {
    notes.reduce((x, note) => {
      note.addToModifierContext(new ModifierContext());
      const tick = new TickContext().addTickable(note).preFormat();
      const extra = tick.getExtraPx();
      tick.setX(x + extra.left);

      return x + tick.getWidth() + extra.right + paddingBetween;
    }, x);
  }
}

--
--
You received this message because you are subscribed to the Google
Groups "vexflow" group.
To post to this group, send email to vex...@googlegroups.com
To unsubscribe from this group, send email to
vexflow+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/vexflow?hl=en

---
You received this message because you are subscribed to the Google Groups "vexflow" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vexflow+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Mohit Muthanna [mohit (at) muthanna (uhuh) com]

danielr...@gmail.com

unread,
Sep 15, 2016, 5:28:34 PM9/15/16
to vexflow, mo...@muthanna.com
Thanks Mohit!  
Still having some trouble.  Would you mind sharing a small example of using the SimpleFormat with a voice?

On Thursday, September 15, 2016 at 9:22:43 AM UTC-7, Mohit Muthanna Cheppudira wrote:
It's probably simpler if you don't use the formatter for this and position then notes manually (using TickContext.setX). E.g., this is how `Formatter.SimpleFormat` places notes for tests without using the main formatter:

static SimpleFormat(notes, x = 0, { paddingBetween = 10 } = {}) {
    notes.reduce((x, note) => {
      note.addToModifierContext(new ModifierContext());
      const tick = new TickContext().addTickable(note).preFormat();
      const extra = tick.getExtraPx();
      tick.setX(x + extra.left);

      return x + tick.getWidth() + extra.right + paddingBetween;
    }, x);
  }
}
On Thu, Sep 15, 2016 at 4:30 AM, <danielr...@gmail.com> wrote:
I'm currently working on a project that requires a horizontal grid, in which all of the quarter note StaveNotes, GhostNotes, and Rests fill the same horizontal space.  I tried to achieve a horizontal space of 40 pixels for each element in a voice by using the following...
let formatter = new Vex.Flow.Formatter().format([hoverVoice], (40 * this.hoverNote.length));

However, this just determines the average space per element.  When there are StaveNotes, GhostNotes, and Rests in the voice StaveNotes take up more than 40 pixels and GhostNotes and Rests take up less than 40 pixels.  Does anyone have any clues on how to make sure that each 1 beat element will take up the exact same horizontal space in a voice?

--
--
You received this message because you are subscribed to the Google
Groups "vexflow" group.
To post to this group, send email to vex...@googlegroups.com
To unsubscribe from this group, send email to

For more options, visit this group at
http://groups.google.com/group/vexflow?hl=en

---
You received this message because you are subscribed to the Google Groups "vexflow" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vexflow+u...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

danielr...@gmail.com

unread,
Sep 15, 2016, 11:54:38 PM9/15/16
to vexflow, mo...@muthanna.com
Here's what I have.
var note = new Vex.Flow.StaveNote({ keys: ['b/4'], duration: "q", clef: 'treble'});;
var tc = new Vex.Flow.TickContext()
note.setTickContext(tc)
tc.setX(10)
note.draw();

I'm getting a "[RuntimeError] NoCanvasContext:Can't draw without a canvas context" with the note.draw().  It looks like the note.draw() looks for this.context and this.stave in which I have both.

On Thursday, September 15, 2016 at 9:22:43 AM UTC-7, Mohit Muthanna Cheppudira wrote:
It's probably simpler if you don't use the formatter for this and position then notes manually (using TickContext.setX). E.g., this is how `Formatter.SimpleFormat` places notes for tests without using the main formatter:

static SimpleFormat(notes, x = 0, { paddingBetween = 10 } = {}) {
    notes.reduce((x, note) => {
      note.addToModifierContext(new ModifierContext());
      const tick = new TickContext().addTickable(note).preFormat();
      const extra = tick.getExtraPx();
      tick.setX(x + extra.left);

      return x + tick.getWidth() + extra.right + paddingBetween;
    }, x);
  }
}
On Thu, Sep 15, 2016 at 4:30 AM, <danielr...@gmail.com> wrote:
I'm currently working on a project that requires a horizontal grid, in which all of the quarter note StaveNotes, GhostNotes, and Rests fill the same horizontal space.  I tried to achieve a horizontal space of 40 pixels for each element in a voice by using the following...
let formatter = new Vex.Flow.Formatter().format([hoverVoice], (40 * this.hoverNote.length));

However, this just determines the average space per element.  When there are StaveNotes, GhostNotes, and Rests in the voice StaveNotes take up more than 40 pixels and GhostNotes and Rests take up less than 40 pixels.  Does anyone have any clues on how to make sure that each 1 beat element will take up the exact same horizontal space in a voice?

--
--
You received this message because you are subscribed to the Google
Groups "vexflow" group.
To post to this group, send email to vex...@googlegroups.com
To unsubscribe from this group, send email to

For more options, visit this group at
http://groups.google.com/group/vexflow?hl=en

---
You received this message because you are subscribed to the Google Groups "vexflow" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vexflow+u...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Mohit Muthanna Cheppudira

unread,
Sep 16, 2016, 10:08:03 AM9/16/16
to vexflow
Hi Daniel, It's simpler if you use Factory and EasyScore to generate your notes, and it will build the elements sanely for you (with context, stave, etc.)


Example:

var vf = new Vex.Flow.Factory({renderer: {selector: 'boo'}});
var score = vf.EasyScore();
var stave = vf.Stave();
var notes = score.notes('C#5/q, B4, A4, G#4'));
notes.forEach(function(note) {
  tc = vf.TickContext();
  note.setTickContext(tc);
  tc.setX(...);
});
vf.draw();



For more options, visit this group at
http://groups.google.com/group/vexflow?hl=en

---
You received this message because you are subscribed to the Google Groups "vexflow" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vexflow+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Mohit Muthanna Cheppudira

unread,
Sep 16, 2016, 10:12:36 AM9/16/16
to vexflow
Note that if you have accidentals and other modifiers on your notes you'll also need this line:

   note.addToModifierContext(vf.ModifierContext());

So, better code is this:

var vf = new Vex.Flow.Factory({renderer: {selector: 'boo'}});
var score = vf.EasyScore();
var stave = vf.Stave();
var notes = score.notes('C#5/q, B4, A4, G#4'));
notes.forEach(function(note) {
  note.addToModifierContext(vf.ModifierContext());
  var tick = new TickContext().addTickable(note).preFormat();
  tick.setX(...);
});
vf.draw();

The preFormat() call makes sure that widths are correctly calculated so that you can deal with overlapping notes (if you care.)

danielr...@gmail.com

unread,
Sep 17, 2016, 2:09:37 PM9/17/16
to vexflow, mo...@muthanna.com
Thanks Mohit, that helps me out a lot!  I have searched through the docs and can't seem to find out how to use ghostnotes or rests with easyscore.  Are these implemented yet?

Mohit Muthanna Cheppudira

unread,
Sep 17, 2016, 2:48:21 PM9/17/16
to vexflow
Add a "/r" to the note to make it a rest (it is positioned by the note value.)

Ghost notes are not implemented, you'll have to build that by hand (but it's simple: "new VF.GhostNote()" and set the width). (If you file a feature request for ghost notes in EasyScore, I'll try to get to it soon.)


For more options, visit this group at
http://groups.google.com/group/vexflow?hl=en

---
You received this message because you are subscribed to the Google Groups "vexflow" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vexflow+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

danielr...@gmail.com

unread,
Sep 17, 2016, 6:49:48 PM9/17/16
to vexflow, mo...@muthanna.com
Thanks Mohit!  It looks like I need more functionality than the easyscore offers.  I solved this by creating a voice full of StaveNotes that are completely transparent and running it through the formatter with the other voices.  Not the most elegant of solutions, but it does the trick for me.

I really appreciate the help,
Daniel
Reply all
Reply to author
Forward
0 new messages