SvgVexFlowBackend.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import Vex = require("vexflow");
  2. import {VexFlowBackend} from "./VexFlowBackend";
  3. import {VexFlowConverter} from "./VexFlowConverter";
  4. import {FontStyles} from "../../../Common/Enums/FontStyles";
  5. import {Fonts} from "../../../Common/Enums/Fonts";
  6. import {RectangleF2D} from "../../../Common/DataObjects/RectangleF2D";
  7. import {PointF2D} from "../../../Common/DataObjects/PointF2D";
  8. import {EngravingRules} from "..";
  9. import {BackendType} from "../../../OpenSheetMusicDisplay";
  10. export class SvgVexFlowBackend extends VexFlowBackend {
  11. private ctx: Vex.Flow.SVGContext;
  12. constructor(rules: EngravingRules) {
  13. super();
  14. this.rules = rules;
  15. }
  16. public getVexflowBackendType(): Vex.Flow.Renderer.Backends {
  17. return Vex.Flow.Renderer.Backends.SVG;
  18. }
  19. public getOSMDBackendType(): BackendType {
  20. return BackendType.SVG;
  21. }
  22. public initialize(container: HTMLElement): void {
  23. this.canvas = document.createElement("div");
  24. this.inner = this.canvas;
  25. this.inner.style.position = "relative";
  26. this.canvas.style.zIndex = "0";
  27. container.appendChild(this.inner);
  28. this.renderer = new Vex.Flow.Renderer(this.canvas, this.getVexflowBackendType());
  29. this.ctx = <Vex.Flow.SVGContext>this.renderer.getContext();
  30. }
  31. public getContext(): Vex.Flow.SVGContext {
  32. return this.ctx;
  33. }
  34. public getSvgElement(): SVGElement {
  35. return this.ctx.svg;
  36. }
  37. public clear(): void {
  38. if (!this.ctx) {
  39. return;
  40. }
  41. //const { svg } = this.ctx; // seems to make svg static between osmd instances.
  42. const svg: SVGElement = this.ctx.svg;
  43. // removes all children from the SVG element,
  44. // effectively clearing the SVG viewport
  45. while (svg.lastChild) {
  46. svg.removeChild(svg.lastChild);
  47. }
  48. // set background color if not transparent
  49. if (this.rules.PageBackgroundColor !== undefined) {
  50. this.ctx.save();
  51. // note that this will hide the cursor
  52. this.ctx.setFillStyle(this.rules.PageBackgroundColor);
  53. this.ctx.fillRect(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);
  54. this.ctx.restore();
  55. }
  56. }
  57. public scale(k: number): void {
  58. this.ctx.scale(k, k);
  59. }
  60. public translate(x: number, y: number): void {
  61. // TODO: implement this
  62. }
  63. public renderText(fontHeight: number, fontStyle: FontStyles, font: Fonts, text: string,
  64. heightInPixel: number, screenPosition: PointF2D, color: string = undefined): void {
  65. this.ctx.save();
  66. if (color) {
  67. this.ctx.attributes.fill = color;
  68. this.ctx.attributes.stroke = color;
  69. }
  70. this.ctx.setFont(this.rules.DefaultFontFamily, fontHeight, VexFlowConverter.fontStyle(fontStyle));
  71. // font size is set by VexFlow in `pt`. This overwrites the font so it's set to px instead
  72. this.ctx.attributes["font-size"] = `${fontHeight}px`;
  73. this.ctx.state["font-size"] = `${fontHeight}px`;
  74. this.ctx.fillText(text, screenPosition.x, screenPosition.y + heightInPixel);
  75. this.ctx.restore();
  76. }
  77. public renderRectangle(rectangle: RectangleF2D, styleId: number, alpha: number = 1): void {
  78. this.ctx.save();
  79. this.ctx.attributes.fill = VexFlowConverter.style(styleId);
  80. this.ctx.attributes["fill-opacity"] = alpha;
  81. this.ctx.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
  82. this.ctx.restore();
  83. this.ctx.attributes["fill-opacity"] = 1;
  84. }
  85. public renderLine(start: PointF2D, stop: PointF2D, color: string = "#FF0000FF", lineWidth: number = 2): void {
  86. this.ctx.save();
  87. this.ctx.beginPath();
  88. this.ctx.moveTo(start.x, start.y);
  89. this.ctx.lineTo(stop.x, stop.y);
  90. this.ctx.attributes.stroke = color;
  91. //this.ctx.attributes.strokeStyle = color;
  92. //this.ctx.attributes["font-weight"] = "bold";
  93. //this.ctx.attributes["stroke-linecap"] = "round";
  94. this.ctx.lineWidth = lineWidth;
  95. this.ctx.stroke();
  96. this.ctx.restore();
  97. }
  98. public renderCurve(points: PointF2D[]): void {
  99. this.ctx.beginPath();
  100. this.ctx.moveTo(points[0].x, points[0].y);
  101. this.ctx.bezierCurveTo(
  102. points[1].x,
  103. points[1].y,
  104. points[2].x,
  105. points[2].y,
  106. points[3].x,
  107. points[3].y
  108. );
  109. this.ctx.lineTo(points[7].x, points[7].y);
  110. this.ctx.bezierCurveTo(
  111. points[6].x,
  112. points[6].y,
  113. points[5].x,
  114. points[5].y,
  115. points[4].x,
  116. points[4].y
  117. );
  118. this.ctx.lineTo(points[0].x, points[0].y);
  119. //this.ctx.stroke();
  120. this.ctx.closePath();
  121. this.ctx.fill();
  122. }
  123. }