VexFlowMusicSheetDrawer.ts 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import Vex = require("vexflow");
  2. import {MusicSheetDrawer} from "../MusicSheetDrawer";
  3. import {RectangleF2D} from "../../../Common/DataObjects/RectangleF2D";
  4. import {VexFlowMeasure} from "./VexFlowMeasure";
  5. import {PointF2D} from "../../../Common/DataObjects/PointF2D";
  6. import {GraphicalLabel} from "../GraphicalLabel";
  7. import {VexFlowConverter} from "./VexFlowConverter";
  8. import {VexFlowTextMeasurer} from "./VexFlowTextMeasurer";
  9. export class VexFlowMusicSheetDrawer extends MusicSheetDrawer {
  10. private renderer: Vex.Flow.Renderer;
  11. private vfctx: Vex.Flow.CanvasContext;
  12. private ctx: CanvasRenderingContext2D;
  13. private titles: HTMLElement;
  14. private zoom: number = 1.0;
  15. constructor(titles: HTMLElement, canvas: HTMLCanvasElement, isPreviewImageDrawer: boolean = false) {
  16. super(new VexFlowTextMeasurer(), isPreviewImageDrawer);
  17. this.renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);
  18. this.vfctx = this.renderer.getContext();
  19. // The following is a hack to retrieve the actual canvas' drawing context
  20. // Not supposed to work forever....
  21. this.ctx = (this.vfctx as any).vexFlowCanvasContext;
  22. this.titles = titles;
  23. }
  24. /**
  25. * Zoom the rendering areas
  26. * @param k is the zoom factor
  27. */
  28. public scale(k: number): void {
  29. this.zoom = k;
  30. this.vfctx.scale(k, k);
  31. }
  32. /**
  33. * Resize the rendering areas
  34. * @param x
  35. * @param y
  36. */
  37. public resize(x: number, y: number): void {
  38. this.renderer.resize(x, y);
  39. }
  40. public translate(x: number, y: number): void {
  41. // Translation seems not supported by VexFlow
  42. this.ctx.translate(x, y);
  43. }
  44. /**
  45. * Converts a distance from unit to pixel space.
  46. * @param unitDistance the distance in units
  47. * @returns {number} the distance in pixels
  48. */
  49. public calculatePixelDistance(unitDistance: number): number {
  50. return unitDistance * 10.0;
  51. }
  52. protected drawMeasure(measure: VexFlowMeasure): void {
  53. measure.setAbsoluteCoordinates(
  54. measure.PositionAndShape.AbsolutePosition.x * 10.0,
  55. measure.PositionAndShape.AbsolutePosition.y * 10.0
  56. );
  57. return measure.draw(this.vfctx);
  58. }
  59. /**
  60. * Renders a Label to the screen (e.g. Title, composer..)
  61. * @param graphicalLabel holds the label string, the text height in units and the font parameters
  62. * @param layer is the current rendering layer. There are many layers on top of each other to which can be rendered. Not needed for now.
  63. * @param bitmapWidth Not needed for now.
  64. * @param bitmapHeight Not needed for now.
  65. * @param heightInPixel the height of the text in screen coordinates
  66. * @param screenPosition the position of the lower left corner of the text in screen coordinates
  67. */
  68. protected renderLabel(graphicalLabel: GraphicalLabel, layer: number, bitmapWidth: number,
  69. bitmapHeight: number, heightInPixel: number, screenPosition: PointF2D): void {
  70. if (screenPosition.y < 0) {
  71. // Temportary solution for title labels
  72. let div: HTMLElement = document.createElement("div");
  73. div.style.fontSize = (graphicalLabel.Label.fontHeight * this.zoom * 10.0) + "px";
  74. //span.style.width = (bitmapWidth * this.zoom * 1.1) + "px";
  75. //span.style.height = (bitmapHeight * this.zoom * 1.1) + "px";
  76. //span.style.overflow = "hidden";
  77. div.style.fontFamily = "Times New Roman";
  78. //span.style.marginLeft = (screenPosition.x * this.zoom) + "px";
  79. div.style.textAlign = "center";
  80. div.appendChild(document.createTextNode(graphicalLabel.Label.text));
  81. this.titles.appendChild(div);
  82. return;
  83. }
  84. let ctx: CanvasRenderingContext2D = (this.vfctx as any).vexFlowCanvasContext;
  85. let old: string = ctx.font;
  86. ctx.font = VexFlowConverter.font(
  87. graphicalLabel.Label.fontHeight * 10.0,
  88. graphicalLabel.Label.fontStyle,
  89. graphicalLabel.Label.font
  90. );
  91. ctx.fillText(graphicalLabel.Label.text, screenPosition.x, screenPosition.y + heightInPixel);
  92. ctx.font = old;
  93. }
  94. /**
  95. * Renders a rectangle with the given style to the screen.
  96. * It is given in screen coordinates.
  97. * @param rectangle the rect in screen coordinates
  98. * @param layer is the current rendering layer. There are many layers on top of each other to which can be rendered. Not needed for now.
  99. * @param styleId the style id
  100. */
  101. protected renderRectangle(rectangle: RectangleF2D, layer: number, styleId: number): void {
  102. let old: string|CanvasGradient|CanvasPattern = this.ctx.fillStyle;
  103. this.ctx.fillStyle = VexFlowConverter.style(styleId);
  104. this.ctx.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
  105. this.ctx.fillStyle = old;
  106. }
  107. /**
  108. * Converts a point from unit to pixel space.
  109. * @param point
  110. * @returns {PointF2D}
  111. */
  112. protected applyScreenTransformation(point: PointF2D): PointF2D {
  113. return new PointF2D(point.x * 10.0, point.y * 10.0);
  114. }
  115. /**
  116. * Converts a rectangle from unit to pixel space.
  117. * @param rectangle
  118. * @returns {RectangleF2D}
  119. */
  120. protected applyScreenTransformationForRect(rectangle: RectangleF2D): RectangleF2D {
  121. return new RectangleF2D(rectangle.x * 10.0, rectangle.y * 10.0, rectangle.width * 10.0, rectangle.height * 10.0);
  122. }
  123. }