Skip to content

stringsync/vexml

Repository files navigation

vexml

https://vexml.dev

Getting Started

Install the package.

npm install @stringsync/vexml

Import the render function.

import { render } from '@stringsync/vexml';

Render MusicXML.

const res = await fetch('song.musicxml'); // or .mxl
const musicXML = await res.text();        // or .blob() for mxl
await render(musicXML, element);

Listening to events

const score = await render(musicXML, element);

let previous = null;

score.addEventListener('pointermove', (e) => {
  const current = e.target?.type === 'note'
    ? e.target
    : null;
  if (current !== previous) {
    previous?.halo.off();
    current?.halo.on('rgba(41, 98, 255, 0.35)');
    previous = current;
  }
});

Using custom fonts

Note

Font family and url are interpolated into a <style> rule and CSS variables. Don't pass raw untrusted user input.

await render(musicXML, element, {
  fonts: {
    // noteheads, clefs, rests, accidentals, etc., default is Bravura
    notation: { family: 'Petaluma' },
    // part/instrument names, lyrics, titles, directions (default is Source Sans 3);
    // optionally specify a font url if it's not already available locally
    text: { family: 'Inter', url: '/fonts/inter.woff2' },
  },
});

Adding a canvas layer

A layer is a <canvas> that you can draw arbitrary content on without affecting the sheet music. vexml controls its size and position.

const score = await render(musicXML, element);

const background = score.addLayer('content', -1); // draws behind the score
// ctx is a standard CanvasRenderingContext2D
background.ctx.fillStyle = 'rgba(0, 0, 255, 0.3)';
background.ctx.fillRect(50, 50, 100, 80);

const foreground = score.addLayer('content', 1); // draws in front of the score
foreground.ctx.fillStyle = 'rgba(255, 0, 0, 0.3)';
foreground.ctx.fillRect(50, 50, 100, 80);

Pass an optional zIndex to order a layer relative to the canvas the score is drawn on, which sits at zIndex 0. A positive value draws in front; a negative value draws behind, showing through the score's transparent pixels. Layers with the same zIndex stack in the order they were created.

Cleaning up

When you're done with a layer or the entire rendered score, call .dispose() to clean up resources.

layer.dispose();
score.dispose();

Development

Dependencies:

Add the repo's bin/ to your PATH so the vex command works anywhere:

profile=~/.${SHELL##*/}rc # ~/.zshrc, ~/.bashrc, etc.
echo "export PATH=\"$PWD/bin:\$PATH\"" >> "$profile"
source "$profile"

Then:

vex dev                     # run the playground site
vex render -i song.musicxml # render a MusicXML file to a png

Don't want it on your PATH? Run it directly with ./bin/vex <command>.

About

MusicXML to Vexflow

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages