فهرست منبع

Fixes to experiments

Andrea Condoluci 9 سال پیش
والد
کامیت
ee0d676ca4
2فایلهای تغییر یافته به همراه368 افزوده شده و 78 حذف شده
  1. 216 19
      experiments/canvas_performance.html
  2. 152 59
      experiments/cursor.html

+ 216 - 19
experiments/canvas_performance.html

@@ -6,9 +6,14 @@
 // * More complex VexFlow systems
 
 // Init function
-window.onload = function() {
-  document.title = "HTML Canvas Memory Tests";
-  document.write("<h1>[OSMD] HTML Canvas Memory Tests</h1>");
+window.onload = function () {
+  window.setTimeout(start, 0);
+}
+
+var start = function () {
+  document.title = "HTML Canvas Performance Tests";
+  document.write("<h1>[OSMD] HTML Canvas Performance Tests</h1>");
+  var t = timer();
   // Run the tests
   repeat(
     "Canvas creation", 100,
@@ -36,7 +41,7 @@ window.onload = function() {
     function(){
       var canvas = document.createElement("canvas");
       canvas.width = 1920;
-      canvas.height = 1080;
+      canvas.height = 200;
       var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);
       var ctx = renderer.getContext();
       for (var j=0; j < 20; j++)
@@ -69,8 +74,27 @@ window.onload = function() {
     }
   );
   repeat(
+    "[VexFlow] Draw systems", 50,
+    "Draw 20 empty staves on a huge canvas (one instrument).",
+    function(){
+      var canvas = document.createElement("canvas");
+      canvas.width = 1920;
+      canvas.height = 1080 * 30;
+      var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);
+      var ctx = renderer.getContext();
+      for (var j=0; j < 20; j++)
+        (new Vex.Flow.Stave(
+          Math.floor(Math.random()*canvas.width),
+          Math.floor(Math.random()*canvas.height),
+          Math.floor(Math.random()*canvas.width)
+        )).addClef("treble")
+          .setContext(ctx)
+          .draw();
+    }
+  );
+  repeat(
     "[VexFlow] Format & draw complex system", 50,
-    "Draw 20 systems with notes, ties and beams on a big canvas (one instrument).",
+    "Draw 20 staves with one voice, ties and beams on a big canvas.",
     function(){
       var canvas = document.createElement("canvas");
       canvas.width = 1920;
@@ -80,7 +104,7 @@ window.onload = function() {
       for (var j=0; j < 20; j++) {
         var stave = new Vex.Flow.Stave(10, 0, 500);
 
-        // Add a treble clef
+        // From the VexFlow Tutorial:
         stave.addClef("treble");
         stave.setContext(ctx).draw();
 
@@ -149,37 +173,210 @@ window.onload = function() {
       }
     }
   );
-  // Finish
-  document.close();
+  repeat(
+    "[VexFlow|big] Format & draw 20 staves 5 voices each.", 50,
+    "...",
+    function(){
+      var canvas = document.createElement("canvas");
+      canvas.width = 1920;
+      canvas.height = 1080;
+      var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);
+      var ctx = renderer.getContext();
+      for (var j=0; j < 20; j++) {
+        var stave = new Vex.Flow.Stave(
+          Math.floor(Math.random()*canvas.width),
+          Math.floor(Math.random()*canvas.height),
+          Math.floor(Math.random()*canvas.width)
+        );
+        stave.addClef("treble");
+        stave.setContext(ctx).draw();
+        var voices = [];
+        for (var i = 0, voice; i < 5; i++) {
+          voice = new Vex.Flow.Voice({
+            num_beats: 4,
+            beat_value: 4,
+            resolution: Vex.Flow.RESOLUTION
+          });
+          voice.addTickables(randomNotes());
+          voices.push(voice);
+        }
+        var formatter = new Vex.Flow.Formatter().
+        joinVoices(voices).format(voices, 500);
+        for (var i = 0; i < 5; i++) {
+          voices[i].draw(ctx, stave);
+        }
+      }
+    }
+  );
+  repeat(
+    "[VexFlow|huge] Format & draw 20 staves with 5 voices each.", 50,
+    "...",
+    function(){
+      var canvas = document.createElement("canvas");
+      canvas.width = 1920;
+      canvas.height = 1080 * 30;
+      var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);
+      var ctx = renderer.getContext();
+      for (var j=0; j < 20; j++) {
+        var stave = new Vex.Flow.Stave(
+          Math.floor(Math.random()*canvas.width),
+          Math.floor(Math.random()*canvas.height),
+          Math.floor(Math.random()*canvas.width)
+        );
+        stave.addClef("treble");
+        stave.setContext(ctx).draw();
+        var voices = [];
+        for (var i = 0, voice; i < 5; i++) {
+          voice = new Vex.Flow.Voice({
+            num_beats: 4,
+            beat_value: 4,
+            resolution: Vex.Flow.RESOLUTION
+          });
+          voice.addTickables(randomNotes());
+          voices.push(voice);
+        }
+        var formatter = new Vex.Flow.Formatter().
+        joinVoices(voices).format(voices, 500);
+        for (var i = 0; i < 5; i++) {
+          voices[i].draw(ctx, stave);
+        }
+      }
+    }
+  );
+
+  var tmp_canvas = document.createElement("canvas");
+  tmp_canvas.width = 1920;
+  tmp_canvas.height = 1080;
+  var tmp_renderer = new Vex.Flow.Renderer(tmp_canvas, Vex.Flow.Renderer.Backends.CANVAS);
+  var ctx = tmp_renderer.getContext();
+  repeat(
+    "[VexFlow|big] Format & draw system", 50,
+    "Draw a measure with a voice.",
+    function(){
+      var stave = new Vex.Flow.Stave(
+        Math.floor(Math.random()*tmp_canvas.width),
+        Math.floor(Math.random()*tmp_canvas.height),
+        Math.floor(Math.random()*tmp_canvas.width)
+      );
+
+      // From the VexFlow Tutorial:
+      stave.addClef("treble");
+      stave.setContext(ctx).draw();
+
+      var notes = [
+        new Vex.Flow.StaveNote({ keys: ["e##/5"], duration: "8d" }).
+        addAccidental(0, new Vex.Flow.Accidental("##")).addDotToAll(),
+        new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "16" }).
+        addAccidental(0, new Vex.Flow.Accidental("b"))
+      ];
+
+      var notes2 = [
+        new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "8" }),
+        new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "16" }),
+        new Vex.Flow.StaveNote({ keys: ["c/4", "e/4"], duration: "16" }).
+        addAccidental(0, new Vex.Flow.Accidental("b"))
+      ];
+
+      var notes3 = [
+        new Vex.Flow.StaveNote({ keys: ["c/4", "e/4"], duration: "8" }),
+        new Vex.Flow.StaveNote({ keys: ["e/4"], duration: "8" }).
+        addAccidental(0, new Vex.Flow.Accidental("#"))
+      ];
+
+      var notes4 = [
+        new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "8" }),
+        new Vex.Flow.StaveNote({ keys: ["e/4"], duration: "8" }),
+      ];
+
+      // Create the beams
+      var beam = new Vex.Flow.Beam(notes);
+      var beam2 = new Vex.Flow.Beam(notes2);
+      var beam3 = new Vex.Flow.Beam(notes3);
+      var beam4 = new Vex.Flow.Beam(notes4);
+
+      // Create a tie between the last note of the first group and the
+      // first note of the last group.
+      var tie = new Vex.Flow.StaveTie({
+        first_note: notes[1],
+        last_note: notes2[0],
+        first_indices: [0],
+        last_indices: [0]
+      });
+
+      // Create another tie between the two chords in the tune
+      var tie2 = new Vex.Flow.StaveTie({
+        first_note: notes2[2],
+        last_note: notes3[0],
+        first_indices: [0, 1],
+        last_indices: [0, 1]
+      });
+
+      var all_notes = notes.concat(notes2).concat(notes3).concat(notes4);
+
+      // Helper function to justify and draw a 4/4 voice
+      Vex.Flow.Formatter.FormatAndDraw(ctx, stave, all_notes);
+
+      // Render beams
+      beam.setContext(ctx).draw();
+      beam2.setContext(ctx).draw();
+      beam3.setContext(ctx).draw();
+      beam4.setContext(ctx).draw();
+
+      // Render ties
+      tie.setContext(ctx).draw();
+      tie2.setContext(ctx).draw();
+    }
+  );
+  finish(t);
 }
 
 //----------------------------------------------------------------------------->
+// Helper functions
+var randomNotes = function () {
+  var notes = [];
+  for (var i = 0, note, key; i < 8; i ++) {
+    key = ("abcdefg".charAt(Math.floor(Math.random()*7))) + "/" + Math.floor(Math.random()*3+2);
+    note = new Vex.Flow.StaveNote({ keys: [key], duration: "8" });
+    notes.push(note);
+  }
+  return notes;
+}
+
+
+//----------------------------------------------------------------------------->
+var finish = function (t) {
+  window.setTimeout(function(){
+    document.write("<hr><p><b>Total Elapsed Time: ~" + Math.floor(t()/1000) + " seconds.</b></p>");
+    document.close();
+  }, 0);
+}
+
 
 // Display the result of a test on the page
 function formatResult(label, descr, times, elapsed) {
-  write("<p><b>" + label + "</b>: " + descr + "<br>");
-  write("<i>Elapsed time: " + (elapsed/times) + "ms each (" + times + " iterations)</i></Op>");
+  document.write("<p><b>" + label + "</b>: " + descr + "<br>");
+  document.write("<i>Elapsed time: " + (elapsed/times) + "ms each (" + times + " iterations)</i></Op>");
 }
 
 // A simple timer
 var timer = function() {
     var start = new Date();
-    return {
-        stop: function() {
-            return (new Date()).getTime() - start.getTime();
-        }
+    return function() {
+      return (new Date()).getTime() - start.getTime();
     }
 }
 
 // Repeat a test
-var repeat = function(label, times, descr, func) {
+var repeat0 = function(label, times, descr, func) {
   var t = timer();
   for (var i = 0; i < times; i++) func();
-  formatResult(label, descr, times, t.stop());
+  formatResult(label, descr, times, t());
+}
+var repeat = function(label, times, descr, func) {
+  window.setTimeout(function(){
+    repeat0(label, times, descr, func);
+  }, 0);
 }
-
-// Write directly on the body
-var write = function(x){document.write(x)}
 
 //----------------------------------------------------------------------------->
 }());</script><!--------------------------------------------------------------->

+ 152 - 59
experiments/cursor.html

@@ -8,106 +8,199 @@
       padding: 0; margin: 0;
     }
     div.big {
-      font-size: 40em;
+      font-size: 10em;
       text-align: center;
+      background: url('cat.png');
+      text-shadow: 1px 1px 1px black;
+      color: white;
+    }
+    div.rep1 {
+      position: fixed;
+      top: 0;
+      left: 0; right: 0;
+      overflow: hidden;
+      box-shadow: 0 0 20px black;
+      background-color: white;
     }
   </style>
 
 <script>(function(){
-var nlines = 5;
-var current = 0;
-var currentWidth = 0;
-var currentX = 0;
+// The layers
+var rep1, main;
 var lines = [];
-var dx = 20;
-var cursor = null;
+var nlines = 3 + Math.floor(Math.random() * 4);
+var current = 0; // current line
+var currentWidth = 0; // the width of current line
 var currentHeight = 0;
-var interval = null;
 var heightSum = 0;
+var currentX = 0; // x of the cursor
+var dx = 20;
+var cursor;
+var interval;
+
+function Cursor() {
+  var cursor1 = document.createElement("img");
+  var cursor2 = document.createElement("img");
+  // Public
+  this.cursor1 = cursor1;
+  this.cursor2 = cursor2;
+  // Set position
+  cursor1.style.position = "absolute";
+  cursor2.style.position = "fixed";
+  // Set z-indices
+  cursor1.style.zIndex = "-1";
+  cursor2.style.zIndex = "-1";
 
-function createGradient(width, height, color) {
-  var c = document.createElement("canvas");
-  c.width = width; c.height = height;
-  var ctx = c.getContext("2d");
-  ctx.globalAlpha = 0.5
-
-  var gradient = ctx.createLinearGradient(0, 0, width, 0);
-  gradient.addColorStop(0, "transparent");
-  gradient.addColorStop(0.5, color);
-  gradient.addColorStop(1, "transparent");
-
-  ctx.fillStyle = gradient;
-  ctx.fillRect(0, 0, width, height);
-  /*
-  // Add top/bottom lines
-  ctx.beginPath();
-  ctx.moveTo(0,1);
-  ctx.lineTo(width, 1);
-  ctx.stroke();
-  */
-  var img = new Image();
-  img.src = c.toDataURL('image/png');
-  img.width = width; img.height = height;
-  document.body.appendChild(img);
-  return img;
+  // Generate a gradient
+  this.style = function (width, height, color) {
+    var c = document.createElement("canvas");
+    c.width = width; c.height = height;
+    var ctx = c.getContext("2d");
+    ctx.globalAlpha = 0.5
+    // Generate the gradient
+    var gradient = ctx.createLinearGradient(0, 0, width, 0);
+    gradient.addColorStop(0, "transparent");
+    gradient.addColorStop(0.5, color);
+    gradient.addColorStop(1, "transparent");
+    ctx.fillStyle = gradient;
+    ctx.fillRect(0, 0, width, height);
+    // Set the images
+    cursor1.src = cursor2.src = c.toDataURL('image/png');
+    cursor1.width  = cursor2.width  = width ;
+    cursor1.height = cursor2.height = height;
+  }
+
+  // Set positions
+  this.set = function (x, y) {
+    cursor1.style.top = heightSum + "px";
+    cursor1.style.left = currentX + "px";
+    cursor2.style.top = heightSum + "px";
+    cursor2.style.left = currentX + "px";
+  }
+  // Display
+  this.show2 = function (vis) {
+    if (vis) {
+      cursor2.style.display = "block";
+    } else {
+      cursor2.style.display = "none";
+    }
+  }
 }
 
 window.onload = function() {
+  window.resizeTo(650, 650);
+
+  cursor = new Cursor();
+
+  rep1 = document.createElement("div");
+  rep1.className = "rep1";
+
+  var helper = document.createElement("div");
+  helper.className = "helper";
+
+  rep1.appendChild(cursor.cursor2);
+  rep1.appendChild(helper);
+
+  main = document.createElement("div");
+  main.className = "main";
+
+  document.body.appendChild(cursor.cursor1);
+  document.body.appendChild(main);
+  document.body.appendChild(rep1);
+
+  //rep1.style.display = "none";
+  // z-indices
+  //main.style.zIndex = "1";
+  //rep1.style.zIndex = "1";
+  //main.style.background = "green";
+  //
   lines = [];
+  var els = [main, helper];
   // fix div colors
-  for (var i = 0; i < nlines; i++) {
+  for (var i = 0; i < nlines; i++)
+    for (var j = 0; j < els.length; j ++) {
     var div = document.createElement("div");
     div.className = "big";
-    lines.push(div); document.body.appendChild(div);
-    div.style.background = i % 2 ? "black" : "white";
-    div.style.color = i % 2 ? "white" : "black";
-    div.textContent = i + 1;
+    if (j === 0)
+      lines.push(div);
+    els[j].appendChild(div);
+    div.innerHTML = (i ? "&nbsp;" : ":") + (i + 1) + (i !== nlines - 1 ? "&nbsp;" : ":");
   }
   // Initialize variabels
   heightSum = 0;
   currentX = 0; currentWidth = -1; current = -1;
   currentHeight = 0;
+  window.setTimeout(init, 1);
+}
+
+function init() {
+  // Fix height
+  rep1.style.height = Math.floor(window.innerHeight / 2) + "px";
   // start animation
-  interval = window.setInterval(step, 100);
+  interval = window.setInterval(step, 20);
 }
 
-function step() {
-  //console.log("step");
+function step () {
   currentX += dx;
+  // We need to go to another staff line
   if (currentX > currentWidth) {
-    current += 1;
     heightSum += currentHeight;
     currentX = 0;
+    current += 1;
     if (current == lines.length) {
-      window.clearInterval(interval);
-      return false;
+      //window.clearInterval(interval);
+      //return false;
+      current = 0;
+      heightSum = 0;
+    }
+    if (current === lines.length - 1) {
+      console.log("Last line: repeat");
+      showRep1(0);
     }
-    window.setTimeout(function(){scrollToLine(current);}, 0);
+    var thenHideSep1 = (current === 0);
+    window.setTimeout(function(){scrollToLine(current, thenHideSep1);}, 0);
     currentWidth = lines[current].offsetWidth - 20;
     currentHeight = lines[current].offsetHeight;
-    // Hide cursor
-    if (cursor)
-      cursor.parentElement.removeChild(cursor);
     // Re-generate cursor
-    cursor = createGradient(20, currentHeight, current % 2 ? "white" : "black");
-    cursor.style.position = "absolute";
-    // Display cursor
-    document.body.appendChild(cursor);
+    cursor.style(20, currentHeight, "black");
   }
-  cursor.style.top = heightSum + "px";
-  cursor.style.left = currentX + "px";
+  cursor.set(heightSum, currentX);
 }
 
-function scrollToLine(line) {
+function scrollToLine(line, thenHideSep1) {
   var height = lines[line].offsetHeight;
   var windowHeight = window.innerHeight;
   var top = Math.max(0, (windowHeight - height) >> 1);
   //window.scrollTo(0, heightSum + top);
-  $('html, body').animate({
-        scrollTop: heightSum - top
-    }, 500);
+  if (thenHideSep1) {
+    // Put the cursor on Sep1
+    cursor.show2(true);
+    $('html, body').animate({
+          scrollTop: heightSum - top
+      }, 500, function() {
+        showRep1();
+      });
+  } else {
+    $('html, body').animate({
+          scrollTop: heightSum - top
+      }, 500);
+  }
+}
+
+// Show or hide repetition view
+function showRep1(line) {
+  if (typeof line !== "undefined") {
+    rep1.scrollTop = 0;
+    //rep1.style.display = "block";
+    $(rep1).fadeIn("slow");
+  } else {
+    // rep1.style.display = "none";
+    $(rep1).fadeOut("fast");
+    cursor.show2(false);
+  }
 }
 
-}());</script>
+}());
+</script>
 </head>
 </html>