vexflow icon indicating copy to clipboard operation
vexflow copied to clipboard

When adding stave notes to a voice, and rendering the accidental doesn't show.

Open ekiim opened this issue 1 year ago • 1 comments

I'm trying to build a small app that renders to assist with the positions and notes for recorders, and I have everything already set up, but I am trying to add a feature to render a stave with the selected notes.

I get the notes in an array similar to this ["C♯4", "E♭4"], but when passing it to the StaveNote and rendering it, the render misses the sharp or flat notation.

This is the code I'm working with.

There is a reference to an Options object, which is the "global state" of the app, and I'm using it as a helper to determine the correct clef and to get the array of selected notes.

When inspecting the keyProps for the StaveNote it does correctly set it as C# or Eb, but... still the rendering of the accidental doesn't show.

What could I be missing?

function DrawStave() {
    const VF = Vex.Flow;
    const element = document.getElementById("vexflow");
    element.innerHTML = "";
    const renderer = new VF.Renderer(element, VF.Renderer.Backends.SVG);
    renderer.resize(410, 120);
    const tuning = Options.tuning;

    const context = renderer.getContext();

    const stave = new VF.Stave(10, 0, 380);
    console.log(stave);
    if (["C5", "F4"].includes(tuning)) {
        stave.addClef("treble")
    }
    else if (["C4"].includes(tuning)) {
        stave.addClef("alto")
    }
    else if (["F3"].includes(tuning)) {
        stave.addClef("bass")
    }
    const notes = (
        ["C4", "C#4", "B4", "F#4", "C4", "A4"]
            .map(e =>
                (e.slice(0, -1) + "/" + e.slice(-1))
                    .replace(/♯/g, "#")
                    .replace(/♭/g, "b")
            )
    )
    stave.setContext(context).draw();
    if (notes.length) {
        const voice = new VF.Voice({ num_beats: notes.length, beat_value: 4 });
        voice.addTickables(
            notes.map(note => new VF.StaveNote({
                keys: [note],
                duration: "q",
                clef: stave.clef,
            }))
        )
        const formatter = new VF.Formatter().joinVoices([voice]).format([voice], 300);
        voice.setStave(stave);
        voice.draw(context, stave);
    }
}

I'm using https://cdn.jsdelivr.net/npm/[email protected]/build/cjs/vexflow.js to include it in the app. (It's a single HTML page with a single javascript file).

ekiim avatar Oct 18 '23 19:10 ekiim

StaveNote constructor ignores the accidentals. You have two options (see https://vexflow.github.io/vexflow-examples/)

  • add the accidental to the note (see step3a)
  • use easy score (see step0)

The examples are using vexflow 5 but the API is the same. The examples also use Factory API but Native API is very similar:

note.addModifier(vf.Accidental({ type: 'b' })) 

vs

note.addModifier(new Accidental( 'b' ))

rvilarl avatar Oct 19 '23 05:10 rvilarl