فهرست منبع

fix(Cursor): position correctly on page 2+ (#817)

fix #817

add the height of previous pages to the y position of the cursor
this is unfortunately necessary right now, because MusicPages all have RelativePosition and AbsolutePosition y=0.
without this, the cursor wouldn't be y-positioned correctly at page numbers > 1.

the div elements of both SVG and Canvas backends now have ids "osmdCanvasPage{pageNumber}".
sschmid 5 سال پیش
والد
کامیت
ca7dffce3c

+ 2 - 0
src/MusicalScore/Graphical/MusicSystemBuilder.ts

@@ -965,6 +965,8 @@ export class MusicSystemBuilder {
      * @returns {GraphicalMusicPage}
      */
     protected createMusicPage(): GraphicalMusicPage {
+        // const previousPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages.last();
+        // const previousSizeY: number = previousPage ? previousPage.PositionAndShape.Size.height : 0;
         const page: GraphicalMusicPage = new GraphicalMusicPage(this.graphicalMusicSheet);
         this.graphicalMusicSheet.MusicPages.push(page);
         page.PageNumber = this.graphicalMusicSheet.MusicPages.length; // caution: page number = page index + 1

+ 8 - 0
src/MusicalScore/Graphical/VexFlow/CanvasVexFlowBackend.ts

@@ -24,6 +24,13 @@ export class CanvasVexFlowBackend extends VexFlowBackend {
         return BackendType.Canvas;
     }
 
+    public getCanvasSize(): number {
+        return document.getElementById("osmdCanvasPage" + this.graphicalMusicPage.PageNumber)?.offsetHeight;
+        // smaller inner canvas:
+        // return Number.parseInt(
+        //     document.getElementById("osmdCanvasVexFlowBackendCanvas" + this.graphicalMusicPage.PageNumber)?.style.height, 10);
+    }
+
     public initialize(container: HTMLElement): void {
         this.canvas = document.createElement("canvas");
         if (!this.graphicalMusicPage) {
@@ -32,6 +39,7 @@ export class CanvasVexFlowBackend extends VexFlowBackend {
         }
         this.canvas.id = "osmdCanvasVexFlowBackendCanvas" + this.graphicalMusicPage.PageNumber; // needed to extract image buffer from js
         this.inner = document.createElement("div");
+        this.inner.id = "osmdCanvasPage" + this.graphicalMusicPage.PageNumber;
         this.inner.style.position = "relative";
         this.canvas.style.zIndex = "0";
         this.inner.appendChild(this.canvas);

+ 5 - 0
src/MusicalScore/Graphical/VexFlow/SvgVexFlowBackend.ts

@@ -26,8 +26,13 @@ export class SvgVexFlowBackend extends VexFlowBackend {
         return BackendType.SVG;
     }
 
+    public getCanvasSize(): number {
+        return document.getElementById("osmdCanvasPage" + this.graphicalMusicPage.PageNumber)?.offsetHeight;
+    }
+
     public initialize(container: HTMLElement): void {
         this.canvas = document.createElement("div");
+        this.canvas.id = "osmdCanvasPage" + this.graphicalMusicPage.PageNumber;
         // this.canvas.id = uniqueID // TODO create unique tagName like with cursor now?
         this.inner = this.canvas;
         this.inner.style.position = "relative";

+ 2 - 0
src/MusicalScore/Graphical/VexFlow/VexFlowBackend.ts

@@ -34,6 +34,8 @@ export abstract class VexFlowBackend {
     return this.canvas;
   }
 
+  public abstract getCanvasSize(): number;
+
   public getRenderElement(): HTMLElement {
     //console.log("backend type: " + this.getVexflowBackendType());
     let renderingHtmlElement: HTMLElement = this.canvas; // for SVGBackend

+ 38 - 3
src/OpenSheetMusicDisplay/Cursor.ts

@@ -7,8 +7,11 @@ import {OpenSheetMusicDisplay} from "./OpenSheetMusicDisplay";
 import {GraphicalMusicSheet} from "../MusicalScore/Graphical/GraphicalMusicSheet";
 import {Instrument} from "../MusicalScore/Instrument";
 import {Note} from "../MusicalScore/VoiceData/Note";
-import {EngravingRules, SourceMeasure, StaffLine} from "../MusicalScore";
 import {Fraction} from "../Common/DataObjects/Fraction";
+import { EngravingRules } from "../MusicalScore/Graphical/EngravingRules";
+import { SourceMeasure } from "../MusicalScore/VoiceData/SourceMeasure";
+import { StaffLine } from "../MusicalScore/Graphical/StaffLine";
+import { GraphicalMeasure } from "../MusicalScore/Graphical/GraphicalMeasure";
 
 /**
  * A cursor which can iterate through the music sheet.
@@ -50,11 +53,14 @@ export class Cursor {
   public iterator: MusicPartManagerIterator;
   private graphic: GraphicalMusicSheet;
   public hidden: boolean = true;
+  public currentPageNumber: number = 1;
+  public pageStartingGraphicalMeasures: GraphicalMeasure[] = [];
 
   /** Initialize the cursor. Necessary before using functions like show() and next(). */
   public init(manager: MusicPartManager, graphic: GraphicalMusicSheet): void {
     this.manager = manager;
     this.graphic = graphic;
+    this.indexPages();
     this.reset();
     this.hidden = true;
     this.hide();
@@ -66,6 +72,7 @@ export class Cursor {
   public show(): void {
     this.hidden = false;
     this.resetIterator(); // TODO maybe not here? though setting measure range to draw, rerendering, then handling cursor show is difficult
+    this.currentPageNumber = 1;
     this.update();
   }
 
@@ -100,7 +107,6 @@ export class Cursor {
   }
 
   public update(): void {
-    // Warning! This should NEVER call this.openSheetMusicDisplay.render()
     if (this.hidden || this.hidden === undefined || this.hidden === null) {
       return;
     }
@@ -124,10 +130,24 @@ export class Cursor {
     if (!musicSystem) {
       return;
     }
+
+    // add the height of previous pages to the y position
+    //   this is unfortunately necessary right now, because MusicPages all have RelativePosition and AbsolutePosition y=0.
+    //   without this, the cursor wouldn't be y-positioned correctly at page numbers > 1.
+    let canvasHeight: number = 0;
+    for (let i: number = 1; i < this.currentPageNumber; i++) {
+      const canvasHeightHTML: number = this.openSheetMusicDisplay.Drawer.Backends[i - 1]?.getCanvasSize();
+      if (canvasHeightHTML > 0) {
+        canvasHeight += canvasHeightHTML / 10;
+      }
+    }
+
     y = musicSystem.PositionAndShape.AbsolutePosition.y + musicSystem.StaffLines[0].PositionAndShape.RelativePosition.y;
+    y += canvasHeight;
     const bottomStaffline: StaffLine = musicSystem.StaffLines[musicSystem.StaffLines.length - 1];
-    const endY: number = musicSystem.PositionAndShape.AbsolutePosition.y +
+    let endY: number = musicSystem.PositionAndShape.AbsolutePosition.y +
     bottomStaffline.PositionAndShape.RelativePosition.y + bottomStaffline.StaffHeight;
+    endY += canvasHeight;
     height = endY - y;
 
     // The following code is not necessary (for now, but it could come useful later):
@@ -184,6 +204,14 @@ export class Cursor {
    */
   public next(): void {
     this.iterator.moveToNext();
+    for (let i: number = 0; i < this.pageStartingGraphicalMeasures.length; i++) {
+      const gMeasure: GraphicalMeasure = this.pageStartingGraphicalMeasures[i];
+      if (this.iterator.CurrentMeasure === gMeasure.parentSourceMeasure) {
+        this.currentPageNumber = i + 1;
+        // this.openSheetMusicDisplay.enableOrDisableCursor(true, true);
+        // break;
+      }
+    }
     this.update();
   }
 
@@ -237,4 +265,11 @@ export class Cursor {
     });
     return notes;
   }
+
+  private indexPages(): void {
+    this.pageStartingGraphicalMeasures = [];
+    for (const page of this.graphic.MusicPages) {
+      this.pageStartingGraphicalMeasures.push(page.MusicSystems[0].GraphicalMeasures[0][0]);
+    }
+  }
 }

+ 10 - 3
src/OpenSheetMusicDisplay/OpenSheetMusicDisplay.ts

@@ -697,26 +697,33 @@ export class OpenSheetMusicDisplay {
     /** Enable or disable (hide) the cursor.
      * @param enable whether to enable (true) or disable (false) the cursor
      */
-    public enableOrDisableCursor(enable: boolean): void {
+    public enableOrDisableCursor(enable: boolean, switchedPage: boolean = false): void {
         this.drawingParameters.drawCursors = enable;
         if (enable) {
             // save previous cursor state
             const hidden: boolean = this.cursor?.Hidden;
             const previousIterator: MusicPartManagerIterator = this.cursor?.Iterator;
+            const previousPageNumber: number = this.cursor?.currentPageNumber ?? 1;
 
+            this.cursor?.hide();
             // create new cursor
             if (this.drawer?.Backends?.length >= 1 && this.drawer.Backends[0].getRenderElement()) {
-                this.cursor = new Cursor(this.drawer.Backends[0].getRenderElement(), this);
+                this.cursor = new Cursor(this.drawer.Backends[previousPageNumber - 1].getRenderElement(), this);
             }
             if (this.sheet && this.graphic && this.cursor) { // else init is called in load()
                 this.cursor.init(this.sheet.MusicPartManager, this.graphic);
             }
 
             // restore old cursor state
-            if (this.rules.RestoreCursorAfterRerender) {
+            if (this.rules.RestoreCursorAfterRerender || switchedPage) {
                 this.cursor.hidden = hidden;
                 if (previousIterator) {
                     this.cursor.iterator = previousIterator;
+                    this.cursor.currentPageNumber = previousPageNumber;
+                    console.log("restore to " + previousPageNumber);
+                }
+                if (switchedPage && !hidden) {
+                    this.cursor.show();
                 }
             }
         } else { // disable cursor