vexflow icon indicating copy to clipboard operation
vexflow copied to clipboard

How to go about switching out notes in a single context

Open rblonski18 opened this issue 3 years ago • 3 comments

I'm currently working on an activity for a website that helps train people with cochlear implants to associate music they're hearing with notes on a screen. The activity plays a song, and at the same time, displays the notes of the song on the screen, in an animation, moving the notes from right to left as they play. I've been using VexFlow for this, and so far it has been exactly what I've needed, but I can really only manage to get the activity stable with a single song / set of notes. When adding a second set of notes, in trying to switch out the notes in the context, they end up not drawing onto the screen, and I'm not really sure why. I created a JSFiddle: https://jsfiddle.net/roryblonski/gme37kxs/7/ This displays the barebones features of the activity I'm building. To explain the issue: I can start and stop a single song as many times as I want, but once I switch to the second song, no notes are displayed. Or, I can go right to the second song and notes are displayed, and I can replay it as many times as I would like, but upon switching back to the first song, none are displayed. I'm new to VexFlow so there might be an obvious way of doing this differently, but I'm mostly just going off of the Animation with VexFlow and CSS tutorial on the wiki. Any help would be greatly appreciated. Thanks a bunch.

rblonski18 avatar Mar 25 '22 00:03 rblonski18

Thanks for including a running example. What a cool demo!

Can you switch the vexflow URL to:

https://unpkg.com/[email protected]/build/cjs/vexflow.js

We just officially shipped VexFlow 4 today, and if we use the most recent URL, we can help you investigate this issue better.

I also noticed that you were including VexFlow twice in the JSFiddle. During development, we usually only include the vexflow-debug.js version:

https://unpkg.com/[email protected]/build/cjs/vexflow-debug.js

Once the app / website is complete, you can remove the "-debug" part and use the smaller JS file instead:

https://unpkg.com/[email protected]/build/cjs/vexflow.js

ronyeh avatar Mar 25 '22 03:03 ronyeh

Hi, I forked your JSFiddle and played around with it.

I think you should try to simplify your code and make sure all the PLAY / STOP / NEXT states work.

For example, I went to your CSS and looked for the opacity settings. Instead of 0, I set the lowest opacity to 0.3.

.correct {
  opacity: 0.3;
}

.deleted {
  opacity: 0.3
}

If you then run your app, you'll see that even after you press STOP or advance to the second song, the first song is still going and notes are still animating.

If you open the Chrome dev tools and inspect the SVG element that is getting created, you'll see that you create a lot of group elements and they never ever get removed. Additionally, the next song's notes are inserted into the last group element, so the opacity values are "multiplied" and the next song's notes are invisible because its parent group is invisible.

Also take a look at your else case:

    } else {
        const group = context.openGroup();
        context.closeGroup();
        group.classList.add("deleted");
        
        for(let j = 0; j < visibleNoteGroups.length; j++) {
            visibleNoteGroups[j].classList.add("deleted")
        } 
        toggleVisibility = false;
    }

If you comment the body out, it might help you debug.

Anyways, I think the Chrome dev tools will help you understand what is going on. I see lots of <g> elements getting created, and they are never removed.

I think when you move to the next song or restart a song, you should probably clear out all the <g> elements and make sure all your timers and animations are stopped and reset.

Good luck!

ronyeh avatar Mar 25 '22 04:03 ronyeh

Thank you so much for the help! I really appreciate it. Added some code to change the else statement to delete all <g> elements in the context and create another tick context. My question is, if I'm writing context.clear() and clearing the context of all <g> elements, how is it that I'm nesting the next song's notes in another <g> tag? And, if I try to run it a third time, the context is removed from the page all together. Why would that happen if I create another context and draw it to the page with the same code used to initialize it at the beginning?

rblonski18 avatar Mar 25 '22 18:03 rblonski18