Skip to content

How to get the HTML element id of a specific note? #549

Closed
@Abefocuson

Description

@Abefocuson

for example

<g class="vf-stavenote" id="vf-auto37980"> ... </g>

how to get "vf-auto37980" ?

Activity

sschmidTU

sschmidTU commented on Jul 18, 2019

@sschmidTU
Contributor

parse it from the SVG using a regular expression.
What do you want to do with this HTML tag or id string though?
I don't see how that would be useful.

sschmidTU

sschmidTU commented on Jul 18, 2019

@sschmidTU
Contributor

Or use an XML Parser of course, e.g. DOMParser
https://developer.mozilla.org/en-US/docs/Web/API/DOMParser

self-assigned this
on Jul 18, 2019
Abefocuson

Abefocuson commented on Jul 18, 2019

@Abefocuson
Author

in this way i can get the specific note in OSMD:

osmd.sheet.sourceMeasures[0].verticalSourceStaffEntryContainers[0].staffEntries[0].voiceEntries[0].notes

and I want to get the HTML element id of this note. Is there a method for me to call to get this id?

sschmidTU

sschmidTU commented on Jul 18, 2019

@sschmidTU
Contributor

No. Why would you want the html element for this? do you want to remove the child element from the SVG? That's the only use i can see for this.
This id is probably generated by the Vexflow SVG Renderer and seems to have an automatically generated id.

If you search through the HTML Elements in the Google Developer Tools, you can see the note highlighted for the vf-stavenote element.
image

But if you want to find this out programmatically, you probably need to do some bounding box calculations.
You can get the OSMD bounding box with note.PositionAndShape, though it will be different from the Vexflow bounding box. One OSMD distance unit is 10 pixels in Vexflow.

sschmidTU

sschmidTU commented on Jul 18, 2019

@sschmidTU
Contributor

If you just want to make a note invisible, call note.PrintObject = false and osmd.render() (included in next release).
Or set note.noteheadColor = "#00000000" (transparent color)

misterallx

misterallx commented on Jul 23, 2019

@misterallx

If you just want to make a note invisible, call note.PrintObject = false and osmd.render() (included in next release).
Or set note.noteheadColor = "#00000000" (transparent color)

When will the next release be available?
Thank you!

sschmidTU

sschmidTU commented on Jul 24, 2019

@sschmidTU
Contributor

When will the next release be available?

hopefully in the next few days.
You should already be able to use the noteheadColor method in the current release though.

dnlfrst

dnlfrst commented on Sep 3, 2019

@dnlfrst
Contributor

Use Case

I do not agree with @sschmidTU's standpoint:

No. Why would you want the html element for this? do you want to remove the child element from the SVG? That's the only use i can see for this.

Currently, I face the need to color a specific subset of note heads upon user interaction.

Issue

It is not possible to use note.noteheadColor for the above use case as this requires a call to render(). In most cases the time necessary to render the music sheet again is too high and disturbs the user interaction.
Manually parsing the DOM does not seem to be feasible as I am not aware of any mapping between a specific ID and its corresponding note in the music sheet.

Solution

It would be beneficial to have access to a note's SVG element ID to do the coloring of its head manually.

As the necessary typings of VexFlow are not exported, I added the required ones manually:

import { GraphicalNote } from 'opensheetmusicdisplay';

declare module 'opensheetmusicdisplay' {
  class VexFlowGraphicalNote extends GraphicalNote {
    vfnote: [any, number];
  }
}

To access the ID or a reference to the note's corresponding SVG element, I use:

const note: GraphicalNote = openSheetMusicDisplay.GraphicSheet.MeasureList[0][0].staffEntries[0].graphicalVoiceEntries[0].notes[0];
const vexFlowNote: VexFlowGraphicalNote = note as VexFlowGraphicalNote;

console.log(vexFlowNote.vfnote[0].getAttribute('id')); // The ID of the note's SVG element.
console.log(vexFlowNote.vfnote[0].getAttribute('el')); // The reference to the note's SVG element.

Question

@sschmidTU do you validate the presented use case? If so, is there any chance to implement the access to the ID of a note's SVG element in a more sophisticated way?

sschmidTU

sschmidTU commented on Sep 3, 2019

@sschmidTU
Contributor

@dnlfrst thank you for the input! the use case is definitely valid, as well as the performance concerns.

The problem is that both OSMD and Vexflow are not well equipped for fast interactive re-rendering like coloring notes with a click at runtime. For any shape changes (instead of just color) we would have to erase at least one measure and redraw it. There's discussion of this elsewhere, e.g. #509.

Your SVG manipulation is a solution for fast recoloring of notes, though you have to admit it's a bit of a hack, because it manipulates low level graphical information, while OSMD tries to solve rendering issues on a high level using Vexflow and its own rendering methods.
Still, if that's what OSMD users need, we should think about providing it.

I've made a commit that exports the VexFlowGraphical classes, so you won't have to export VexFlowGraphicalNote manually anymore.
(These not being exported was just an oversight, because the create-ts-index script we use mysteriously leaves out a few classes and folders)

As for methods that get the note's SVG element [id], you have already written them:

    public getSVGId(): string {
        return this.vfnote[0].getAttribute("id");
    }

    public getSVGGElement(): SVGGElement {
        return this.vfnote[0].getAttribute("el");
    }

By the way, is SVGGElement the correct Typescript class here? I've never used it.
edit: getSVGGElement().constructor.name says it's SVGGElement

osmd.GraphicSheet.MeasureList[0][0].staffEntries[0].graphicalVoiceEntries[0].notes[0].getSVGGElement().constructor.name

So, for your purposes, you could just add these methods in your code somewhere as a meta-API, and you wouldn't need them from OSMD.

But we've thought about it and wouldn't mind adding these methods to VexFlowGraphicalNote. People who use this to manipulate the SVG should know that they're engaging in low level hacks, and then we won't stop them.

By the way, i'm not sure how one could access the SVG element "in a more sophisticated way", but since as i said this is a hack anyways with simple code, i don't see a reason to.

dnlfrst

dnlfrst commented on Sep 4, 2019

@dnlfrst
Contributor

Thank you for the in-depth answer and your continuous efforts, @sschmidTU!

The problem is that both OSMD and Vexflow are not well equipped for fast interactive re-rendering like coloring notes with a click at runtime.

Yes, this probably depends on #352 and #396?

Your SVG manipulation is a solution for fast recoloring of notes, though you have to admit it's a bit of a hack, because it manipulates low level graphical information, while OSMD tries to solve rendering issues on a high level using Vexflow and its own rendering methods.

Totally a hack, it does not seem right to fiddle with the generated SVG elements.

I've made a commit that exports the VexFlowGraphical classes, so you won't have to export VexFlowGraphicalNote manually anymore.
(These not being exported was just an oversight, because the create-ts-index script we use mysteriously leaves out a few classes and folders)

That's great, thank you!

But we've thought about it and wouldn't mind adding these methods to VexFlowGraphicalNote.

Nice, I noticed your commit (3dbe83b) for that.

By the way, i'm not sure how one could access the SVG element "in a more sophisticated way", but since as i said this is a hack anyways with simple code, i don't see a reason to.

Probably not phrased correctly, I was referring to some way that does not involve adding custom types or even going without them. However, I think that's covered with f0f63fd and 3dbe83b.

7 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @Abefocuson@dnlfrst@sschmidTU@misterallx@yuvalha96

      Issue actions

        How to get the HTML element id of a specific note? · Issue #549 · opensheetmusicdisplay/opensheetmusicdisplay