Vexflow: Is music score animation possible in Vexflow?

Created on 25 Feb 2017  Â·  29Comments  Â·  Source: 0xfe/vexflow

Dear all,
I just came across VexFlow - kudos to the developer(s). As a new user, I'm wondering if it's possible to animate music scores using VexFlow? I'm creating a sight reading application and I would like to do something like this:

notes

Is this type of animation possible in VexFlow?

Any suggestions or feedback much appreciated.

A.

Most helpful comment

The wiki page on animation is complete!

All 29 comments

Yes -- while no one to my knowledge has created exactly an app like this, I am confident that it can be done in VexFlow + Javascript.

Here's a similar example using VexFlow. Outer div with overflow hidden. Inner div wide enough for the full score. Use CSS transition and transform/translate on the inner div to get the animation.

Similar example

Interesting approach. Here is a jsfiddle, is this the effect you used? What if I want to make the notes change colour or disappear based on a user event? (e.g. similar to your example)

Haha, I was asking myself the same question as I'm building my own personal sight reading app right now.

@antonioaguilar If you find anything useful in that regard (with or without vexflow), I'd be happy to hear from you ;)

Awesome demo, Gregory! :-)

On Sat, Feb 25, 2017 at 6:23 PM, Gregory Ristow notifications@github.com
wrote:

Here's a similar example using VexFlow. Outer div with overflow hidden.
Inner div wide enough for the full score. Use CSS transition and
transform/translate on the inner div to get the animation.

Similar example https://m.youtube.com/watch?v=6PqmWgs67bc

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/0xfe/vexflow/issues/538#issuecomment-282520060, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAOuk3-fB9cDnpI7mLcwOKNAg4rjGoBxks5rgLgFgaJpZM4MMCpJ
.

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

Yep, @antonioaguilar, that's just about exactly how I did it. Depending on the complexity of the scores you're rendering, you may just be able to re-render the full score in the div that's being scrolled, with notes colored in response to a user event.

Alternately, the SVG context allows you to open groups with SVGContext.openGroup, which will return an SVG group element. To get these as you draw your notes, do something like this:

const svgNoteGroups = notesToDraw.map(staveNote => {
  const group = context.openGroup();
  staveNote.setContext(context).draw();
  context.closeGroup();
  return group;
});

From there you can remove or style the notes like this:

// To make a note disappear:
context.svg.removeChild(svgNoteGroups[0]);

// Or to make it disappear more creatively:
svgNoteGroups[0].style.transition = "opacity 2s, transform 2s"
svgNoteGroups[0].style.opacity = '0';
svgNoteGroups[0].style.transform = "translate(0, -1000px)";

// To color it:
svgNoteGroups[0].setAttribute("fill", "red");

I played a bit with the idea from above and by layering two svgs (absolute positioning) you can render one base staff having the clef and time signature, while having the other one (slightly shorter) lay on top and scrolling through the notes (staff without left and right border, clef or signature).

You can't see its two staves on top on each other and its a really nice effect (actually just like the one in the start post).

@gristow thank you for suggesting the approach- I'm not very familiar (yet) with SVG context but I'm going to try it out. In my case, I'm not expecting complex scores (whole notes mostly). I have a particular sight reading exercise which requires the user to recognise and play notes as fast as possible without timing signature. Events will come from MIDI or the computer keyboard, so I have to be able to fade out the notes as soon as they are played. So, I'm considering to apply your approach, perhaps using VelocityJS since I read that has nice support for SVG animation and has excellent performance.

No problem. If scrolling & fading is all you need to do, CSS transform/translate and opacity are hardware accelerated on pretty much every device, so you get quite good performance there. In the example above, the "more creative" fading out approach I suggest will both fade out the note and make it fly up and out of view at the same time just with vanilla JavaScript and CSS.

But if you need to do more complex things (including smoothly changing the scroll rate mid-scroll -- say to make it more difficult or easy -- which turns out to be quite difficult with CSS), you might find a library like VelocityJS or GreenSock more helpful.

Thanks for the suggestion but right now, I'm struggling with the VexFlow/EasyScore API - I can't get VexFlow to display a long sequence of notes (100) without time signature constraints. See jsfiddle. I can see VexFlow is quite powerful but can't get it to do what I want to do ... any suggestions or examples?

Short version: the EasyScore API, at this point, is strict about beats-per-measure. But given what you're doing, you might in the end, frankly, prefer to handle the drawing of notes on your staff manually, as needed. (This would allow you to, for instance, start putting notes closer together if the user was doing well, or more spaced apart if they were struggling to read fast enough.)

I'll try and do a JSFiddle later (I'm running off to a rehearsal right now), but you might look first at the VexFlow tutorial to see how to use SVGContext instead of EasyScore, and then at tests/stavenote_tests.js to see how notes can be manually drawn.

@antonioaguilar, I had a few minutes this morning to do a fiddle which I think probably gets pretty close to what you're looking for. (Unfortunately because I used ES2015 arrow functions & such it's not so good in Safari right now, but that should be relatively easily fixed.)

Click "Add Note" to start scrolling a note, "Right Answer" to simulate a user playing it correctly.

SUPER COOL! and btw in El Capitan Safari arrow functions work fine!

Nice demonstration, thank you!

Love it. Maybe drop it in the wiki somewhere?

On Tue, Feb 28, 2017 at 2:56 PM, Patrick Bauer notifications@github.com
wrote:

Nice demonstration, thank you!

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/0xfe/vexflow/issues/538#issuecomment-283144886, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAOuk3sPRJAmKt7jTqZypdvtc9LioJOJks5rhHv0gaJpZM4MMCpJ
.

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

@gristow thank you for taking the time to make this wonderful demo! It was exactly what I wanted to do. This demo will be useful to VexFlow newbies, specially the sections that show how to generate sequence of notes.

Happy to add this to the wiki somewhere -- any suggestions on a helpful/descriptive title? Maybe "Animation with VexFlow & CSS"?

The wiki page on animation is complete!

Thanks Gregory! That's very thoughtfully written. Well done! :-)

On Wed, Mar 1, 2017 at 9:33 AM, Gregory Ristow notifications@github.com
wrote:

The wiki page on animation
https://github.com/0xfe/vexflow/wiki/Animation-with-VexFlow-&-CSS is
complete!

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/0xfe/vexflow/issues/538#issuecomment-283355585, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAOuk2XqvEF23Krqq9LidM6vXfKKuVPfks5rhYGggaJpZM4MMCpJ
.

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

Here is a gist and jsFiddle to do flow animation with 100% Javascript. I like the control of Javascript instead of leaving it to CSS, but that might just be me being lazy

https://gist.github.com/stevenkaspar/da7e740562408848eeb30f81074b2773
https://jsfiddle.net/stevenkaspar/8gLbetyy/

edit: @gristow, awesome work!

@stevenkaspar nice solution -- and of course if you needed super smooth motion (which setInterval() won't always give you) you could use requestAnimationFrame() if available too.

@gristow can you complete the @stevenkaspar example with your recomendations?

It is a awesome example!

@gristow thanks for the recommendation! I haven't done much that requires advanced UI stuff so I didn't know about that function

I have updated the gist & fiddle to use requestAnimationFrame()

@stevenkaspar, I'm going to close out this issue -- but I want to be sure we preserve a reference to your excellent approach, gist & fiddle.

We have an Animation with VexFlow & CSS wiki page now. Would you consider creating one for Animation with VexFlow & JavaScript? (Or, if not, adding a reference to your fiddle in the Animating w/ CSS page?)

I will work on a new page. Probably won't get to it until next weekend
though

On Sun, Jun 18, 2017 at 9:52 AM, Gregory Ristow notifications@github.com
wrote:

@stevenkaspar https://github.com/stevenkaspar, I'm going to close out
this issue -- but I want to be sure we preserve a reference to your
excellent approach, gist & fiddle.

We have an Animation with VexFlow & CSS
https://github.com/0xfe/vexflow/wiki/Animation-with-VexFlow-&-CSS wiki
page now. Would you consider creating one for Animation with VexFlow &
JavaScript? (Or, if not, adding a reference to your fiddle in the Animating
w/ CSS page?)

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/0xfe/vexflow/issues/538#issuecomment-309282264, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AGkLMOjj2BqLlEZUIKdaC5N1Hs7S0ZMmks5sFTnLgaJpZM4MMCpJ
.

@stevenkaspar VelocityJS could have been an alternative for SVG animation.

@stevenkaspar, it will be great to have whenever you can get to it!

@antonioaguilar -- totally, if you want to do serious animation & co-ordination of multiple moving elements VelocityJS, GreenSock, or Snap.svg would all be great choices. (I'm sure there are others I don't know of, too.)

I think it's nice in this example, where it's basically a simple transformation animation, to see how it can be done with vanilla JavaScript.

Is there any Vex example of a score player that plays a MIDI/MusicXML file with a cursor (the usual vertical red bar...) following the notes played?

I need to render a 4 score set like this
http://www.solfege.it

that's done with 4 synced mp3 and static image...
I'd like to go directly with the midi files...
any suggestion?

@gristow To hide a voice, instead of opening a group from the context with a:

const voiceGroup: any = context.openGroup();
voice.draw(context);
context.closeGroup(); 

can we do a:

voiceGroup: vexflow.Flow.VoiceGroup = voice.getVoiceGroup();

but then it seems that we can't get a reference to the style:

voiceGroup.style.opacity = '0';

So instead I explicitly created a group:

const staveGroup: any = context.openGroup();
stave.draw();
voice.draw(context);
context.closeGroup();

But then, when I later hide the group, it only hides the stave and not its voices.

So I added another group creation for the voices.

And yet another group creation for the highlighting of the chords, plus another one for the un-highlighting.

I have to add a group for each call to the draw() method, and keeping the references to all these groups.

A better way would be to not draw, but change the properties of an existing chord, when highlighting it for example.

But I took a different path. I decided to draw over the existing content, first a white rectangle filling up the space, and then my content.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rowild picture rowild  Â·  5Comments

jeroenlammerts picture jeroenlammerts  Â·  4Comments

aemion picture aemion  Â·  3Comments

FlyMantou picture FlyMantou  Â·  3Comments

devboell picture devboell  Â·  6Comments