瀏覽代碼

fix(Cursor): Enable cursor options/styles like highlight current measure (#33)

sschmid 3 年之前
父節點
當前提交
70a379dc2c
共有 3 個文件被更改,包括 43 次插入39 次删除
  1. 1 0
      demo/index.js
  2. 5 5
      src/MusicalScore/Graphical/GraphicalMusicSheet.ts
  3. 37 34
      src/OpenSheetMusicDisplay/Cursor.ts

+ 1 - 0
demo/index.js

@@ -456,6 +456,7 @@ import { TransposeCalculator } from '../src/Plugins/Transpose/TransposeCalculato
             autoResize: true,
             backend: backendType,
             //backend: "canvas",
+            //cursorsOptions: [{type: 3, color: "#2bb8cd", alpha: 0.6, follow: true}], // highlight current measure instead of just a small vertical bar over approximate notes
             disableCursor: false,
             drawingParameters: compactMode ? "compact" : "default", // try compact (instead of default)
             drawPartNames: true, // try false

+ 5 - 5
src/MusicalScore/Graphical/GraphicalMusicSheet.ts

@@ -844,7 +844,7 @@ export class GraphicalMusicSheet {
     }
 
     public calculateCursorLineAtTimestamp(musicTimestamp: Fraction, styleEnum: OutlineAndFillStyleEnum): GraphicalLine {
-        const result: [number, MusicSystem] = this.calculateXPositionFromTimestamp(musicTimestamp);
+        const result: [number, MusicSystem, any] = this.calculateXPositionFromTimestamp(musicTimestamp);
         const xPos: number = result[0];
         const correspondingMusicSystem: MusicSystem = result[1];
         if (!correspondingMusicSystem || correspondingMusicSystem.StaffLines.length === 0) {
@@ -855,14 +855,14 @@ export class GraphicalMusicSheet {
         return new GraphicalLine(new PointF2D(xPos, yCoordinate), new PointF2D(xPos, yCoordinate + height), 3, styleEnum);
     }
 
-    public calculateXPositionFromTimestamp(timeStamp: Fraction): [number, MusicSystem] {
+    public calculateXPositionFromTimestamp(timeStamp: Fraction): [number, MusicSystem, GraphicalStaffEntry] {
         let currentMusicSystem: MusicSystem = undefined;
         const fractionalIndex: number = this.GetInterpolatedIndexInVerticalContainers(timeStamp);
         const previousStaffEntry: GraphicalStaffEntry = this.findClosestLeftStaffEntry(fractionalIndex, true);
         const nextStaffEntry: GraphicalStaffEntry = this.findClosestRightStaffEntry(fractionalIndex, true);
         const currentTimeStamp: number = timeStamp.RealValue;
         if (!previousStaffEntry && !nextStaffEntry) {
-            return [0, undefined];
+            return [0, undefined, undefined];
         }
         let previousStaffEntryMusicSystem: MusicSystem = undefined;
         if (previousStaffEntry) {
@@ -903,7 +903,7 @@ export class GraphicalMusicSheet {
             }
             fraction = Math.min(1, Math.max(0, fraction));
             const interpolatedXPosition: number = previousStaffEntryPositionX + fraction * (nextStaffEntryPositionX - previousStaffEntryPositionX);
-            return [interpolatedXPosition, currentMusicSystem];
+            return [interpolatedXPosition, currentMusicSystem, previousStaffEntry];
         } else {
             const nextSystemLeftBorderTimeStamp: number = nextStaffEntry.parentMeasure.parentSourceMeasure.AbsoluteTimestamp.RealValue;
             let fraction: number;
@@ -925,7 +925,7 @@ export class GraphicalMusicSheet {
                 fraction = Math.min(1, Math.max(0, fraction));
                 interpolatedXPosition = nextSystemLeftBorderX + fraction * (nextStaffEntryPositionX - nextSystemLeftBorderX);
             }
-            return [interpolatedXPosition, currentMusicSystem];
+            return [interpolatedXPosition, currentMusicSystem, previousStaffEntry];
         }
     }
 

+ 37 - 34
src/OpenSheetMusicDisplay/Cursor.ts

@@ -14,7 +14,7 @@ import { StaffLine } from "../MusicalScore/Graphical/StaffLine";
 import { GraphicalMeasure } from "../MusicalScore/Graphical/GraphicalMeasure";
 import { VexFlowMeasure } from "../MusicalScore/Graphical/VexFlow/VexFlowMeasure";
 import { CursorOptions } from "./OSMDOptions";
-import { BoundingBox } from "../MusicalScore";
+import { BoundingBox, GraphicalStaffEntry } from "../MusicalScore";
 import { IPlaybackListener } from "../Common/Interfaces/IPlaybackListener";
 import { CursorPosChangedData } from "../Common/DataObjects/CursorPosChangedData";
 import { PointF2D } from "../Common/DataObjects";
@@ -145,25 +145,28 @@ export class Cursor implements IPlaybackListener {
   public updateWithTimestamp(timestamp: Fraction): void {
     const sheetTimestamp: Fraction = this.manager.absoluteEnrolledToSheetTimestamp(timestamp);
 
-    const values: [number, MusicSystem] = this.graphic.calculateXPositionFromTimestamp(sheetTimestamp);
+    const values: [number, MusicSystem, GraphicalStaffEntry] = this.graphic.calculateXPositionFromTimestamp(sheetTimestamp);
     const x: number = values[0];
     const currentSystem: MusicSystem = values[1];
     this.updateCurrentPageFromSystem(currentSystem);
+    const previousStaffEntry: GraphicalStaffEntry = values[2];
+
+    const topMeasureNumber: number = previousStaffEntry.parentMeasure.MeasureNumber;
+    // we have to find the top measure, otherwise the cursor with type 3 "jumps around" between vertical measures
+    let topMeasure: GraphicalMeasure;
+    for (const measure of this.graphic.MeasureList[topMeasureNumber - 1]) {
+      if (measure) {
+        topMeasure = measure;
+        break;
+      }
+    }
 
     const points: [PointF2D, PointF2D] = this.graphic.calculateCursorPoints(x, currentSystem);
     const y: number = points[0].y;
     const height: number = points[1].y - y;
 
-    // This the current HTML Cursor:
-    const cursorElement: HTMLImageElement = this.cursorElement;
-    cursorElement.style.top = (y * 10.0 * this.openSheetMusicDisplay.zoom) + "px";
-    cursorElement.style.left = ((x - 1.5) * 10.0 * this.openSheetMusicDisplay.zoom) + "px";
-    cursorElement.height = (height * 10.0 * this.openSheetMusicDisplay.zoom);
-    const newWidth: number = 3 * 10.0 * this.openSheetMusicDisplay.zoom;
-    if (newWidth !== cursorElement.width) {
-      cursorElement.width = newWidth;
-      this.updateStyle(newWidth);
-    }
+    this.updateWidthAndStyle(topMeasure.PositionAndShape, x, y, height);
+
     if (this.openSheetMusicDisplay.FollowCursor) {
       const diff: number = this.cursorElement.getBoundingClientRect().top;
       this.cursorElement.scrollIntoView({behavior: diff < 1000 ? "smooth" : "auto", block: "center"});
@@ -225,15 +228,26 @@ export class Cursor implements IPlaybackListener {
     bottomStaffline.PositionAndShape.RelativePosition.y + bottomStaffline.StaffHeight;
     height = endY - y;
 
+    const measurePositionAndShape: BoundingBox = this.graphic.findGraphicalMeasure(iterator.CurrentMeasureIndex, 0).PositionAndShape;
     // Update the graphical cursor
-    // The following is the legacy cursor rendered on the canvas:
-    // // let cursor: GraphicalLine = new GraphicalLine(new PointF2D(x, y), new PointF2D(x, y + height), 3, OutlineAndFillStyleEnum.PlaybackCursor);
+    this.updateWidthAndStyle(measurePositionAndShape, x, y, height);
 
-    // This the current HTML Cursor:
-    const cursorElement: HTMLImageElement = this.cursorElement;
+    if (this.openSheetMusicDisplay.FollowCursor) {
+      if (!this.openSheetMusicDisplay.EngravingRules.RenderSingleHorizontalStaffline) {
+        const diff: number = this.cursorElement.getBoundingClientRect().top;
+        this.cursorElement.scrollIntoView({behavior: diff < 1000 ? "smooth" : "auto", block: "center"});
+      } else {
+        this.cursorElement.scrollIntoView({behavior: "smooth", inline: "center"});
+      }
+    }
+    // Show cursor
+    // // Old cursor: this.graphic.Cursors.push(cursor);
+    this.cursorElement.style.display = "";
+  }
 
+  public updateWidthAndStyle(measurePositionAndShape: BoundingBox, x: number, y: number, height: number): void {
+    const cursorElement: HTMLImageElement = this.cursorElement;
     let newWidth: number = 0;
-    const meassurePositionAndShape: BoundingBox = this.graphic.findGraphicalMeasure(iterator.CurrentMeasureIndex, 0).PositionAndShape;
     switch (this.cursorOptions.type) {
       case 1:
         cursorElement.style.top = (y * 10.0 * this.openSheetMusicDisplay.zoom) + "px";
@@ -248,16 +262,16 @@ export class Cursor implements IPlaybackListener {
         newWidth = 5 * this.openSheetMusicDisplay.zoom;
         break;
       case 3:
-        cursorElement.style.top = meassurePositionAndShape.AbsolutePosition.y * 10.0 * this.openSheetMusicDisplay.zoom +"px";
-        cursorElement.style.left = meassurePositionAndShape.AbsolutePosition.x * 10.0 * this.openSheetMusicDisplay.zoom +"px";
+        cursorElement.style.top = measurePositionAndShape.AbsolutePosition.y * 10.0 * this.openSheetMusicDisplay.zoom +"px";
+        cursorElement.style.left = measurePositionAndShape.AbsolutePosition.x * 10.0 * this.openSheetMusicDisplay.zoom +"px";
         cursorElement.height = (height * 10.0 * this.openSheetMusicDisplay.zoom);
-        newWidth = meassurePositionAndShape.Size.width * 10 * this.openSheetMusicDisplay.zoom;
+        newWidth = measurePositionAndShape.Size.width * 10 * this.openSheetMusicDisplay.zoom;
         break;
       case 4:
-        cursorElement.style.top = meassurePositionAndShape.AbsolutePosition.y * 10.0 * this.openSheetMusicDisplay.zoom +"px";
-        cursorElement.style.left = meassurePositionAndShape.AbsolutePosition.x * 10.0 * this.openSheetMusicDisplay.zoom +"px";
+        cursorElement.style.top = measurePositionAndShape.AbsolutePosition.y * 10.0 * this.openSheetMusicDisplay.zoom +"px";
+        cursorElement.style.left = measurePositionAndShape.AbsolutePosition.x * 10.0 * this.openSheetMusicDisplay.zoom +"px";
         cursorElement.height = (height * 10.0 * this.openSheetMusicDisplay.zoom);
-        newWidth = (x-meassurePositionAndShape.AbsolutePosition.x) * 10 * this.openSheetMusicDisplay.zoom;
+        newWidth = (x-measurePositionAndShape.AbsolutePosition.x) * 10 * this.openSheetMusicDisplay.zoom;
         break;
         default:
         cursorElement.style.top = (y * 10.0 * this.openSheetMusicDisplay.zoom) + "px";
@@ -271,17 +285,6 @@ export class Cursor implements IPlaybackListener {
       cursorElement.width = newWidth;
       this.updateStyle(newWidth, this.cursorOptions);
     }
-    if (this.openSheetMusicDisplay.FollowCursor) {
-      if (!this.openSheetMusicDisplay.EngravingRules.RenderSingleHorizontalStaffline) {
-        const diff: number = this.cursorElement.getBoundingClientRect().top;
-        this.cursorElement.scrollIntoView({behavior: diff < 1000 ? "smooth" : "auto", block: "center"});
-      } else {
-        this.cursorElement.scrollIntoView({behavior: "smooth", inline: "center"});
-      }
-    }
-    // Show cursor
-    // // Old cursor: this.graphic.Cursors.push(cursor);
-    this.cursorElement.style.display = "";
   }
 
   /**