소스 검색

Added page format selector and render pdf button for demo project.

Matthias Uiberacker 5 년 전
부모
커밋
e263ad5d9e
5개의 변경된 파일138개의 추가작업 그리고 7개의 파일을 삭제
  1. 15 0
      demo/index.html
  2. 19 1
      demo/index.js
  3. 20 0
      src/MusicalScore/Graphical/EngravingRules.ts
  4. 3 0
      src/OpenSheetMusicDisplay/OSMDOptions.ts
  5. 81 6
      src/OpenSheetMusicDisplay/OpenSheetMusicDisplay.ts

+ 15 - 0
demo/index.html

@@ -126,6 +126,21 @@
             </div>
         </div>
     </div>
+    <div class="column">
+        <h3 class="ui header">Page size:</h3>
+        <select class="ui selection dropdown" id="selectPageSize">
+            <option value="endless">endless</option>
+            <option value="A3 P">A3 Portrait</option>
+            <option value="A3 L">A3 Landscape</option>
+            <option value="A4 P">A4 Portrait</option>
+            <option value="A4 L">A4 Landscape</option>
+            <option value="A5 P">A5 Portrait</option>
+            <option value="A5 L">A5 Landscape</option>
+            <option value="Letter P">Letter Portrait</option>
+            <option value="Letter L">Letter Landscape</option>
+        </select>
+        <div class="ui button" id="print-pdf-btn">Print to Pdf</div>
+    </div>
 </div>
 <div id="optionalControls"></div>
 <table cellspacing="0" style="max-width:700px;">

+ 19 - 1
demo/index.js

@@ -70,7 +70,9 @@ import { OpenSheetMusicDisplay } from '../src/OpenSheetMusicDisplay/OpenSheetMus
         hideCursorBtn,
         backendSelect,
         debugReRenderBtn,
-        debugClearBtn;
+        debugClearBtn,
+        selectPageSize,
+        printPdfBtn;
 
     // manage option setting and resetting for specific samples, e.g. in the autobeam sample autobeam is set to true, otherwise reset to previous state
     // TODO design a more elegant option state saving & restoring system, though that requires saving the options state in OSMD
@@ -142,6 +144,8 @@ import { OpenSheetMusicDisplay } from '../src/OpenSheetMusicDisplay/OpenSheetMus
         backendSelect = document.getElementById("backend-select");
         debugReRenderBtn = document.getElementById("debug-re-render-btn");
         debugClearBtn = document.getElementById("debug-clear-btn");
+        selectPageSize = document.getElementById("selectPageSize");
+        printPdfBtn = document.getElementById("print-pdf-btn");
 
         if (!showControls) {
             divControls.style.display = 'none';
@@ -181,6 +185,20 @@ import { OpenSheetMusicDisplay } from '../src/OpenSheetMusicDisplay/OpenSheetMus
             selectBounding.onchange = selectBoundingOnChange;
         }
 
+        if (selectPageSize) {
+            selectPageSize.onchange = function (evt) {
+                var value = evt.target.value;
+                openSheetMusicDisplay.setPageFormat(value);
+                openSheetMusicDisplay.render();
+            };
+        }
+
+        if (printPdfBtn) {
+            printPdfBtn.onclick = function () {
+                openSheetMusicDisplay.createPdf();
+            }
+        }
+
         // Pre-select default music piece
 
         custom.appendChild(document.createTextNode("Custom"));

+ 20 - 0
src/MusicalScore/Graphical/EngravingRules.ts

@@ -213,6 +213,7 @@ export class EngravingRules {
     /** Position of fingering label in relation to corresponding note (left, right supported, above, below experimental) */
     private fingeringPosition: PlacementEnum;
     private fingeringInsideStafflines: boolean;
+    private pageFormat: PageFormat;
 
     constructor() {
         // global variables
@@ -1540,6 +1541,13 @@ export class EngravingRules {
         this.fingeringInsideStafflines = value;
     }
 
+    public get PageFormat(): PageFormat {
+        return this.pageFormat;
+    }
+    public set PageFormat(value: PageFormat) {
+        this.pageFormat = value;
+    }
+
     /**
      * This method maps NoteDurations to Distances and DistancesScalingFactors.
      */
@@ -1601,3 +1609,15 @@ export class EngravingRules {
         }
     }
 }
+
+export class PageFormat {
+    constructor(width: number, height: number) {
+        this.width = width;
+        this.height = height;
+    }
+    public width: number;
+    public height: number;
+    public get aspectRatio(): number {
+        return this.width / this.height;
+    }
+}

+ 3 - 0
src/OpenSheetMusicDisplay/OSMDOptions.ts

@@ -1,4 +1,5 @@
 import { DrawingParametersEnum, ColoringModes } from "../MusicalScore/Graphical/DrawingParameters";
+import { PageFormat } from "../MusicalScore/Graphical/EngravingRules";
 
 /** Possible options for the OpenSheetMusicDisplay constructor and osmd.setOptions(). None are mandatory.
  *  Note that after using setOptions(), you have to call osmd.render() again to make changes visible.
@@ -110,6 +111,8 @@ export interface IOSMDOptions {
     tripletsBracketed?: boolean;
     /** Whether to draw hidden/invisible notes (print-object="no" in XML). Default false. Not yet supported. */ // TODO
     drawHiddenNotes?: boolean;
+
+    pageFormat?: PageFormat;
 }
 
 export enum AlignRestOption {

+ 81 - 6
src/OpenSheetMusicDisplay/OpenSheetMusicDisplay.ts

@@ -15,7 +15,7 @@ import { AJAX } from "./AJAX";
 import * as log from "loglevel";
 import { DrawingParametersEnum, DrawingParameters, ColoringModes } from "../MusicalScore/Graphical/DrawingParameters";
 import { IOSMDOptions, OSMDOptions, AutoBeamOptions } from "./OSMDOptions";
-import { EngravingRules } from "../MusicalScore/Graphical/EngravingRules";
+import { EngravingRules, PageFormat } from "../MusicalScore/Graphical/EngravingRules";
 import { AbstractExpression } from "../MusicalScore/VoiceData/Expressions/AbstractExpression";
 import { Dictionary } from "typescript-collections";
 import { NoteEnum } from "..";
@@ -178,7 +178,12 @@ export class OpenSheetMusicDisplay {
         // Set page width
         const width: number = this.container.offsetWidth;
         this.sheet.pageWidth = width / this.zoom / 10.0;
-        EngravingRules.Rules.PageHeight = this.sheet.pageWidth * 1.41;
+        if (EngravingRules.Rules.PageFormat) {
+            EngravingRules.Rules.PageHeight = this.sheet.pageWidth / EngravingRules.Rules.PageFormat.aspectRatio;
+        } else {
+            EngravingRules.Rules.PageHeight = 100001.0;
+        }
+
         // Before introducing the following optimization (maybe irrelevant), tests
         // have to be modified to ensure that width is > 0 when executed
         //if (isNaN(width) || width === 0) {
@@ -199,21 +204,26 @@ export class OpenSheetMusicDisplay {
         this.drawer.Backends.clear();
 
         // create new backends
-        for (const {} of this.graphic.MusicPages) {
+        for (const page of this.graphic.MusicPages) {
             const backend: VexFlowBackend = this.createBackend(this.backendType);
-            backend.resize(width, width * 1.41);
+            if (EngravingRules.Rules.PageFormat) {
+                backend.resize(width, width / EngravingRules.Rules.PageFormat.aspectRatio);
+            } else {
+                backend.resize(width, (page.PositionAndShape.Size.height + 15) * this.zoom * 10.0);
+            }
             this.drawer.Backends.push(backend);
         }
         this.drawer.setZoom(this.zoom);
         // Finally, draw
         this.drawer.drawSheet(this.graphic);
-        this.createPdf(this.sheet.FullNameString + ".pdf", this.drawer.Backends);
         if (this.drawingParameters.drawCursors && this.cursor) {
             // Update the cursor position
             this.cursor.update();
         }
     }
 
+
+
     /** States whether the render() function can be safely called. */
     public IsReadyToRender(): boolean {
         return this.graphic !== undefined;
@@ -257,6 +267,14 @@ export class OpenSheetMusicDisplay {
         // }
 
         // Create the drawer
+        if (this.drawer) {
+            // Remove old backends
+            for (const backend of this.drawer.Backends) {
+                backend.removeFromContainer(this.container);
+            }
+            this.drawer.Backends.clear();
+        }
+
         this.drawer = new VexFlowMusicSheetDrawer(this.drawingParameters);
 
         //this.enableOrDisableCursor(this.drawingParameters.drawCursors);
@@ -394,6 +412,9 @@ export class OpenSheetMusicDisplay {
             this.autoResizeEnabled = false;
             // we could remove the window EventListener here, but not necessary.
         }
+
+        // no if -> shall also be set to undefined:
+        EngravingRules.Rules.PageFormat = options.pageFormat;
     }
 
     public setColoringMode(options: IOSMDOptions): void {
@@ -587,8 +608,62 @@ export class OpenSheetMusicDisplay {
         return backend;
     }
 
-    public createPdf(pdfName: string, backends: VexFlowBackend[], pageWidth: number = 210, pageHeight: number = 297): void {
+    public static PageFormatStandards: {[type: string]: PageFormat} = {
+        "A3 L": new PageFormat(420, 297),
+        "A3 P": new PageFormat(297, 420),
+        "A4 L": new PageFormat(297, 210),
+        "A4 P": new PageFormat(210, 297),
+        "A5 L": new PageFormat(210, 148),
+        "A5 P": new PageFormat(148, 210),
+        "A6 L": new PageFormat(148, 105),
+        "A6 P": new PageFormat(105, 148),
+        "Letter L": new PageFormat(279.4, 215.9),
+        "Letter P": new PageFormat(215.9, 279.4)
+    };
+
+    public setPageFormat(formatId: string): void {
+        let f: PageFormat = undefined;
+        if (OpenSheetMusicDisplay.PageFormatStandards.hasOwnProperty(formatId)) {
+            f = OpenSheetMusicDisplay.PageFormatStandards[formatId];
+        }
+        const options: IOSMDOptions = {
+            pageFormat: f,
+        };
+        this.setOptions(options);
+    }
+
+    public setCustomPageFormat(width: number, height: number): void {
+        if (width > 0 && height > 0) {
+            const f: PageFormat = new PageFormat(width, height);
+            const options: IOSMDOptions = {
+                pageFormat: f,
+            };
+            this.setOptions(options);
+        }
+    }
+
+    /**
+     * Creates a Pdf of the currently rendered MusicXML
+     * @param pdfName if no name is given, the composer and title of the piece will be used
+     */
+    public createPdf(pdfName: string = undefined): void {
+
+        if (pdfName === undefined) {
+            pdfName = this.sheet.FullNameString + ".pdf";
+        }
+
+        const backends: VexFlowBackend[] =  this.drawer.Backends;
         let svgElement: SVGElement = (<SvgVexFlowBackend>backends[0]).getSvgElement();
+
+        let pageWidth: number = 210;
+        let pageHeight: number = 297;
+        if (EngravingRules.Rules.PageFormat) {
+            pageWidth = EngravingRules.Rules.PageFormat.width;
+            pageHeight = EngravingRules.Rules.PageFormat.height;
+        } else {
+            pageHeight = pageWidth * svgElement.clientHeight / svgElement.clientWidth;
+        }
+
         const orientation: string = pageHeight > pageWidth ? "p" : "l";
         // create a new jsPDF instance
         const pdf: any = new jspdf(orientation, "mm", [pageWidth, pageHeight]);