Trying to animate notes fading from clear to black sequentially

3 views
Skip to first unread message

Steve Naughton

unread,
Sep 21, 2025, 1:01:58 AM (9 days ago) Sep 21
to vexflow
Hi all,
I am trying to display an arpeggio with each note appearing as a fade in, in sequence, but there are two problems:
1) the SVG fading is not working - but I should be able to solve this with a lot more trial and error.  My next trial will be using javascript instead of css.  If anyone has any better ways, please let me know.
2) the ledger lines for middle C and B5 are not considered part of the note in VexFlow, and do not fade in with the note.  I suppose the answer is to get those ledger line elements from the SVG separately and animate those, but that doesn't really suit my purposes.  Again, does anyone have any suggestions on better ways of going about this problem?

<html>
  <head>
    <!-- IMPORTANT: Set the character set to UTF-8. Otherwise you may get weird symbols on the score. -->
    <meta charset="utf-8" />
    <style>
        .fade-in {
            color: #000;
        opacity: 1;
        transition: opacity 1s ease-in;
        }
    </style>    
  </head>
  <body>
    <!-- Div where the scores will be output -->
    <div id="output"></div>

    <!-- Load library -->

    <script src="test6.js"></script>
  </body>
</html>


    const black = "#000000";
    var context;
    var notes = [];
    var currNote = 0;
    function drawnote() {
        if (currNote >= notes.length) {
            window.clearInterval(); // Stop the interval when all notes are drawn
            return;
        }
        let note = notes[currNote++];
        note.setStyle({ fillStyle: black, strokeStyle: black });
        const group = context.openGroup();
        group.classList.add("fade-in");
        note.draw();
        context.closeGroup();
    }  

    window.onload = function() {
        setInterval(drawnote, 1000); // Calls yourMethod every 1000ms (1 second)
    };

/* global VexFlow */

      VexFlow.loadFonts('Bravura', 'Academico').then(() => {
      VexFlow.setFonts('Bravura', 'Academico');
      const factory = new VexFlow.Factory({
        renderer: { elementId: 'output', width: 250, height: 150 },
      });
      context = factory.context;


      const score = factory.EasyScore();

      notes = score.notes('C4/q, F#4, B5, Bb4');
      let voice = score.voice(notes);
      const system = factory.System();
      system.addStave({voices: [voice]}).addClef('treble').addTimeSignature('4/4');

      let invisible = "#00000000";
      for (let note of notes){
        note.setStyle({ fillStyle: invisible, strokeStyle: invisible });
      }

      factory.draw();

      for (let note of notes){
        const svg = note.getSVGElement();
        if (svg) {
            svg.classList.add('fade-in');
        }
      }
});

Steve Naughton

unread,
Sep 21, 2025, 1:15:10 PM (9 days ago) Sep 21
to vexflow
I got it working.  I used javascript to animate SVG instead of CSS.  
To eliminate the ledger lines, you need to set the fill and stroke attributes on the note.getSVGElement() node, plus ALL of its children:
function setNoteColor(note, color) {
    var svgEle = note.getSVGElement();
    svgEle.setAttribute('fill', color);
    svgEle.setAttribute('stroke', color);
    const children = svgEle.children;

    for (let i = 0; i < children.length; i++) {
        const child = children[i];
        child.setAttribute('fill', color);
        child.setAttribute('stroke', color);
    }
}

Reply all
Reply to author
Forward
0 new messages