浏览代码

feat(color): add colorStemsLikeNoteheads option, color beams like stems as well if matching

part of #486
sschmidTU 6 年之前
父节点
当前提交
b63187934d

+ 5 - 3
demo/index.js

@@ -239,12 +239,14 @@ import { OpenSheetMusicDisplay } from '../src/OpenSheetMusicDisplay/OpenSheetMus
         if (str.includes("auto-custom-coloring")) {
             //openSheetMusicDisplay.setOptions({coloringMode: 1}); // Auto-Coloring with pre-defined colors
             openSheetMusicDisplay.setOptions({
-                coloringMode: 2,
-                coloringSetCustom: ["#d82c6b", "#F89D15", "#FFE21A", "#4dbd5c", "#009D96", "#43469d", "#76429c", "#ff0000"]
+                coloringMode: 2, // custom coloring set. 0 would be XML, 1 autocoloring
+                coloringSetCustom: ["#d82c6b", "#F89D15", "#FFE21A", "#4dbd5c", "#009D96", "#43469d", "#76429c", "#ff0000"],
                 // last color value of coloringSetCustom is for rest notes
+
+                colorStemsLikeNoteheads: true
             });
         } else {
-            openSheetMusicDisplay.setOptions({coloringMode: 0});
+            openSheetMusicDisplay.setOptions({coloringMode: 0, colorStemsLikeNoteheads: false});
         }
         openSheetMusicDisplay.setOptions({autoBeam: str.includes("autobeam")});
         openSheetMusicDisplay.setOptions({drawPartAbbreviations: !str.includes("Schubert_An_die_Musik")}); // TODO weird layout bug here. but shouldn't be in score anyways

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

@@ -181,6 +181,7 @@ export class EngravingRules {
 
     private coloringMode: ColoringMode;
     private coloringEnabled: boolean;
+    private colorStemsLikeNoteheads: boolean;
     private colorFlags: boolean;
     private colorBeams: boolean;
     private coloringSetCustom: Dictionary<NoteEnum|number, string>;
@@ -398,6 +399,7 @@ export class EngravingRules {
         // Render options (whether to render specific or invisible elements)
         this.coloringMode = ColoringMode.XML;
         this.coloringEnabled = true;
+        this.colorStemsLikeNoteheads = false;
         this.colorBeams = true;
         this.colorFlags = true;
         this.defaultColorNotehead = "#000000"; // black. undefined is only black if a note's color hasn't been changed before.
@@ -1350,6 +1352,12 @@ export class EngravingRules {
     public set ColoringEnabled(value: boolean) {
         this.coloringEnabled = value;
     }
+    public get ColorStemsLikeNoteheads(): boolean {
+        return this.colorStemsLikeNoteheads;
+    }
+    public set ColorStemsLikeNoteheads(value: boolean) {
+        this.colorStemsLikeNoteheads = value;
+    }
     public get ColorFlags(): boolean {
         return this.colorFlags;
     }

+ 27 - 4
src/MusicalScore/Graphical/GraphicalVoiceEntry.ts

@@ -8,6 +8,7 @@ import { VexFlowVoiceEntry } from "./VexFlow/VexFlowVoiceEntry";
 import { EngravingRules } from "./EngravingRules";
 import { ColoringModes } from "./DrawingParameters";
 import { NoteEnum } from "../../Common/DataObjects/Pitch";
+import { Note } from "..";
 
 /**
  * The graphical counterpart of a [[VoiceEntry]].
@@ -46,12 +47,13 @@ export class GraphicalVoiceEntry extends GraphicalObject {
         const defaultColorRest: string = EngravingRules.Rules.DefaultColorRest;
         const defaultColorStem: string = EngravingRules.Rules.DefaultColorStem;
         const transparentColor: string = "#00000000"; // transparent color in vexflow
+        let noteheadColor: string; // if null: no noteheadcolor to set (stays black)
 
         const vfStaveNote: any = (<VexFlowVoiceEntry>(this as any)).vfStaveNote;
         for (let i: number = 0; i < this.notes.length; i++) {
             const note: GraphicalNote = this.notes[i];
 
-            let noteheadColor: string = note.sourceNote.NoteheadColor;
+            noteheadColor = note.sourceNote.NoteheadColor;
             // Switch between XML colors and automatic coloring
             if (EngravingRules.Rules.ColoringMode === ColoringModes.AutoColoring ||
                 EngravingRules.Rules.ColoringMode === ColoringModes.CustomColorSet) {
@@ -90,11 +92,27 @@ export class GraphicalVoiceEntry extends GraphicalObject {
                 continue;
             }
 
+            // color notebeam if all noteheads have same color and stem coloring enabled
+            if (note.sourceNote.NoteBeam && EngravingRules.Rules.ColorStemsLikeNoteheads) {
+                const beamNotes: Note[] = note.sourceNote.NoteBeam.Notes;
+                let colorBeam: boolean = true;
+                for (let j: number = 0; j < beamNotes.length; j++) {
+                    if (beamNotes[j].NoteheadColor !== noteheadColor) {
+                        colorBeam = false;
+                    }
+                }
+                if (colorBeam) {
+                    if (vfStaveNote.beam !== null && vfStaveNote.beam.setStyle) {
+                        vfStaveNote.beam.setStyle({ fillStyle: noteheadColor, strokeStyle: noteheadColor});
+                    }
+                }
+            }
+
             if (vfStaveNote) {
                 if (vfStaveNote.note_heads) { // see VexFlowConverter, needs Vexflow PR
                     const notehead: any = vfStaveNote.note_heads[i];
                     if (notehead) {
-                        vfStaveNote.note_heads[i].setStyle({ fillStyle: noteheadColor, strokeStyle: noteheadColor });
+                        notehead.setStyle({ fillStyle: noteheadColor, strokeStyle: noteheadColor });
                     }
                 }
             }
@@ -102,8 +120,13 @@ export class GraphicalVoiceEntry extends GraphicalObject {
 
         // color stems
         let stemColor: string = this.parentVoiceEntry.StemColor;
-        if (!stemColor && defaultColorStem) {
-            stemColor = defaultColorStem;
+        const autoColoring: boolean = EngravingRules.Rules.ColoringMode !== ColoringModes.XML; // TODO: once custom color set gets stem color, respect it
+        if (!stemColor || autoColoring) {
+            if (EngravingRules.Rules.ColorStemsLikeNoteheads && noteheadColor) {
+                stemColor = noteheadColor;
+            } else if (defaultColorStem) {
+                stemColor = defaultColorStem;
+            }
         }
         let stemTransparent: boolean = true;
         for (const note of this.parentVoiceEntry.Notes) {

+ 3 - 1
src/OpenSheetMusicDisplay/OSMDOptions.ts

@@ -19,8 +19,10 @@ export interface IOSMDOptions {
     coloringMode?: ColoringModes;
     /** Set of 8 colors for automatic coloring of 7 notes from C to B + rest note in HTML form (e.g. "#00ff00" for green).  */
     coloringSetCustom?: string[];
-    /** Whether to enable coloring noteheads and stems by their XML color attribute. */
+    /** Whether to enable coloring noteheads and stems, depending on coloringMode. */
     coloringEnabled?: boolean;
+    /** Whether to color the stems of notes the same as their noteheads */
+    colorStemsLikeNoteheads?: boolean;
     /** Default color for a note head (without stem). Default black (undefined). */
     defaultColorNotehead?: string;
     /** Default color for a note stem. Default black (undefined). */

+ 3 - 0
src/OpenSheetMusicDisplay/OpenSheetMusicDisplay.ts

@@ -252,6 +252,9 @@ export class OpenSheetMusicDisplay {
         if (options.coloringEnabled !== undefined) {
             EngravingRules.Rules.ColoringEnabled = options.coloringEnabled;
         }
+        if (options.colorStemsLikeNoteheads !== undefined) {
+            EngravingRules.Rules.ColorStemsLikeNoteheads = options.colorStemsLikeNoteheads;
+        }
         if (options.disableCursor) {
             this.drawingParameters.drawCursors = false;
             this.enableOrDisableCursor(this.drawingParameters.drawCursors);