Canvas vs SVG issues in rendering, using vexflow

553 views
Skip to first unread message

Craig Morrison

unread,
Jan 31, 2015, 12:26:55 PM1/31/15
to vex...@googlegroups.com

Hey all, I just put together a really simple test page, to see if I could get vexflow to render music for me.  It worked, after much hair pulling, but the results were NOT consistent, if I used the canvas element vs. the SVG element.

Take a look at the attached image above.  For some odd reason, the canvas version is stretching out the music beyond the size of the canvas itself, and compressing the look of things.  Weird.

Any ideas why this may be happening?  The musical snippet should be familiar to anyone who has gone through the vexflow tutorial (as that's where I got it from).


I have a desire to fully harness vexflow for a responsive web app, so I have to start somewhere.

Also, another question...

In order to get this to render at all, with either canvas or svg,  I had to alter a line of code found in the tutorial.

The original snippet opened with these lines:

 var canvas = $("div.two div.a canvas")[0];
 var renderer = new Vex.Flow.Renderer(canvas,
 Vex.Flow.Renderer.Backends.CANVAS);


That gave me a blank screen.... so I changed it to this:

var canvas = document.getElementById("score1")
    var renderer = new Vex.Flow.Renderer(canvas,
    Vex.Flow.Renderer.Backends.RAPHAEL);

Mohit Muthanna Cheppudira

unread,
Jan 31, 2015, 12:31:15 PM1/31/15
to vex...@googlegroups.com
On Sat, Jan 31, 2015 at 12:26 PM, Craig Morrison <frogmor...@gmail.com> wrote:

Hey all, I just put together a really simple test page, to see if I could get vexflow to render music for me.  It worked, after much hair pulling, but the results were NOT consistent, if I used the canvas element vs. the SVG element.

Take a look at the attached image above.  For some odd reason, the canvas version is stretching out the music beyond the size of the canvas itself, and compressing the look of things.  Weird.

Any ideas why this may be happening?  The musical snippet should be familiar to anyone who has gone through the vexflow tutorial (as that's where I got it from).

Can you post the code (and the html)? I'm almost certain the canvas is being scaled incorrectly.
 


I have a desire to fully harness vexflow for a responsive web app, so I have to start somewhere.

Also, another question...

In order to get this to render at all, with either canvas or svg,  I had to alter a line of code found in the tutorial.

The original snippet opened with these lines:

 var canvas = $("div.two div.a canvas")[0];
 var renderer = new Vex.Flow.Renderer(canvas,
 Vex.Flow.Renderer.Backends.CANVAS);


That gave me a blank screen.... so I changed it to this:

var canvas = document.getElementById("score1")
    var renderer = new Vex.Flow.Renderer(canvas,
    Vex.Flow.Renderer.Backends.RAPHAEL);

This is because your're missing '$' which comes from jQuery. 

--
--
You received this message because you are subscribed to the Google
Groups "vexflow" group.
To post to this group, send email to vex...@googlegroups.com
To unsubscribe from this group, send email to
vexflow+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/vexflow?hl=en

---
You received this message because you are subscribed to the Google Groups "vexflow" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vexflow+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Mohit Muthanna [mohit (at) muthanna (uhuh) com]

Craig Morrison

unread,
Jan 31, 2015, 1:07:19 PM1/31/15
to vex...@googlegroups.com
Here's the code:

<!DOCTYPE html>
<html>
  <script src="js/raphael.js"></script>
  <script src="js/vexflow-min.js"></script>
  <style type="text/css">
    #score1 {
      border: 1px solid black;
      width: 600px;
      height: 150px;
    }

    #score2 {
      border: 1px solid black;
      width: 600px;
      height: 150px;
    }


  </style>
  <body>
    <p>SVG test:</p>
   <svg id="score1"></svg>
   <p>Canvas test:</p>
    <canvas id="score2"></canvas>
  </body>
  <script>
    var canvas = document.getElementById("score1")
    var renderer = new Vex.Flow.Renderer(canvas,
    Vex.Flow.Renderer.Backends.RAPHAEL);

  var ctx = renderer.getContext();
  var stave = new Vex.Flow.Stave(10, 0, 500);
  stave.addClef("treble").setContext(ctx).draw();

  // Create the notes
  var notes = [
    // A quarter-note C.
    new Vex.Flow.StaveNote({ keys: ["c/4"], duration: "q" }),

    // A quarter-note D.
    new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "q" }),

    // A quarter-note rest. Note that the key (b/4) specifies the vertical
    // position of the rest.
    new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "qr" }),

    // A C-Major chord.
    new Vex.Flow.StaveNote({ keys: ["c/4", "e/4", "g/4"], duration: "q" })
  ];

  // Create a voice in 4/4
  var voice = new Vex.Flow.Voice({
    num_beats: 4,
    beat_value: 4,
    resolution: Vex.Flow.RESOLUTION
  });

  // Add notes to voice
  voice.addTickables(notes);

  // Format and justify the notes to 500 pixels
  var formatter = new Vex.Flow.Formatter().
    joinVoices([voice]).format([voice], 500);

  // Render voice
  voice.draw(ctx, stave);

//CANVAS RENDERING CODE BELOW 

  var canvas = document.getElementById("score2")
    var renderer = new Vex.Flow.Renderer(canvas,
    Vex.Flow.Renderer.Backends.CANVAS);

  var ctx = renderer.getContext();
  var stave = new Vex.Flow.Stave(10, 0, 500);
  stave.addClef("treble").setContext(ctx).draw();

  // Create the notes
  var notes = [
    // A quarter-note C.
    new Vex.Flow.StaveNote({ keys: ["c/4"], duration: "q" }),

    // A quarter-note D.
    new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "q" }),

    // A quarter-note rest. Note that the key (b/4) specifies the vertical
    // position of the rest.
    new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "qr" }),

    // A C-Major chord.
    new Vex.Flow.StaveNote({ keys: ["c/4", "e/4", "g/4"], duration: "q" })
  ];

  // Create a voice in 4/4
  var voice = new Vex.Flow.Voice({
    num_beats: 4,
    beat_value: 4,
    resolution: Vex.Flow.RESOLUTION
  });

  // Add notes to voice
  voice.addTickables(notes);

  // Format and justify the notes to 500 pixels
  var formatter = new Vex.Flow.Formatter().
    joinVoices([voice]).format([voice], 500);

  // Render voice
  voice.draw(ctx, stave);

  </script>
</html>

Mohit Muthanna Cheppudira

unread,
Jan 31, 2015, 1:16:18 PM1/31/15
to vex...@googlegroups.com
Yep, the problem is that you're scaling (and therefore distorting) the canvas using its CSS width/height attributes. To set the resolution of your canvas correctly, you use the width and height parameters of the tag.

Here's your example corrected: http://jsfiddle.net/L5tgokfj/

--
--
You received this message because you are subscribed to the Google
Groups "vexflow" group.
To post to this group, send email to vex...@googlegroups.com
To unsubscribe from this group, send email to
vexflow+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/vexflow?hl=en

---
You received this message because you are subscribed to the Google Groups "vexflow" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vexflow+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Craig Morrison

unread,
Jan 31, 2015, 3:03:55 PM1/31/15
to vex...@googlegroups.com
Thanks a bunch, Mohit!  Can you speak to the other problem a bit more?  I don't understand what the hightlighted line is doing, with the dollarsign.  I know you said it's JQuery (another library), but can you explain the syntax in that line?  for example, the [0] seems like it is referring to the first item of an array or something.  Sorry to ask such a basic question...  

Mohit Muthanna Cheppudira

unread,
Jan 31, 2015, 3:56:40 PM1/31/15
to vex...@googlegroups.com
Yes, that's from jQuery. It's a shortcut for DOM selection. In your
example you could have used $("#score1") instead of
document.getElementById("score1").

See: http://www.w3schools.com/jquery/jquery_ref_selectors.asp

Craig Morrison

unread,
Jan 31, 2015, 9:36:21 PM1/31/15
to vex...@googlegroups.com
Thank you so much! I'll be in touch in this group. You did a great job with vexflow, btw.

Henri Augusto

unread,
Apr 20, 2015, 12:04:18 AM4/20/15
to vex...@googlegroups.com, mo...@muthanna.com
Hi, Mohit Muthanna!

Sorry for bothering over this issue, but it has been intriguing me for the entire day.But i still can't understand that JQuery selector even after reading over the entire HTML, CSS and JQuery tutorials. For what i understand it does

"select all "canvas" inside a "div" of class "a" that is inside a "div" of class "two".

Indeed there's an "a" class in your .css file. But i couldn't find a "two" class, neither an "one" or so on.
At first i thought it should somewhat select the second div element, but that's not the syntax for that.
Also, i didn't found nothing about it on the web after 30min of searching.

 var canvas = $("div.two div.a canvas")[0];

 var renderer = new Vex.Flow.Renderer(canvas,
 Vex.Flow.Renderer.Backends.CANVAS);


I already got it working with document.getElementById(""), but i must understand it, otherwise i won't sleep hahah

Thanks for your attention! :)

Mohit Muthanna Cheppudira

unread,
Apr 20, 2015, 8:10:00 AM4/20/15
to Henri Augusto, vex...@googlegroups.com
If you search the source for "description", you'll find divs named "description one", "description two", etc. (These are two classes applied to the div, "description", and "one"/"two"/...)
Reply all
Reply to author
Forward
0 new messages