UNPKG

vexflow

Version:

A JavaScript library for rendering music notation and guitar tablature.

113 lines (112 loc) 4.45 kB
import { CanvasContext } from './canvascontext.js'; import { SVGContext } from './svgcontext.js'; import { isRenderContext } from './typeguard.js'; import { RuntimeError } from './util.js'; import { isHTMLCanvas, isHTMLDiv } from './web.js'; export var RendererBackends; (function (RendererBackends) { RendererBackends[RendererBackends["CANVAS"] = 1] = "CANVAS"; RendererBackends[RendererBackends["SVG"] = 2] = "SVG"; })(RendererBackends || (RendererBackends = {})); export var RendererLineEndType; (function (RendererLineEndType) { RendererLineEndType[RendererLineEndType["NONE"] = 1] = "NONE"; RendererLineEndType[RendererLineEndType["UP"] = 2] = "UP"; RendererLineEndType[RendererLineEndType["DOWN"] = 3] = "DOWN"; })(RendererLineEndType || (RendererLineEndType = {})); export class Renderer { static buildContext(elementId, backend, width, height, background = '#FFF') { const renderer = new Renderer(elementId, backend); if (width && height) { renderer.resize(width, height); } const ctx = renderer.getContext(); ctx.setBackgroundFillStyle(background); Renderer.lastContext = ctx; return ctx; } static getCanvasContext(elementId, width, height, background) { return Renderer.buildContext(elementId, Renderer.Backends.CANVAS, width, height, background); } static getSVGContext(elementId, width, height, background) { return Renderer.buildContext(elementId, Renderer.Backends.SVG, width, height, background); } static drawDashedLine(context, fromX, fromY, toX, toY, dashPattern) { context.beginPath(); const dx = toX - fromX; const dy = toY - fromY; const angle = Math.atan2(dy, dx); let x = fromX; let y = fromY; context.moveTo(fromX, fromY); let idx = 0; let draw = true; while (!((dx < 0 ? x <= toX : x >= toX) && (dy < 0 ? y <= toY : y >= toY))) { const dashLength = dashPattern[idx++ % dashPattern.length]; const nx = x + Math.cos(angle) * dashLength; x = dx < 0 ? Math.max(toX, nx) : Math.min(toX, nx); const ny = y + Math.sin(angle) * dashLength; y = dy < 0 ? Math.max(toY, ny) : Math.min(toY, ny); if (draw) { context.lineTo(x, y); } else { context.moveTo(x, y); } draw = !draw; } context.closePath(); context.stroke(); } constructor(arg0, arg1) { if (isRenderContext(arg0)) { this.ctx = arg0; } else { if (arg1 === undefined) { throw new RuntimeError('InvalidArgument', 'Missing backend argument'); } const backend = arg1; let element; if (typeof arg0 === 'string') { const maybeElement = document.getElementById(arg0); if (!maybeElement) { throw new RuntimeError('BadElementId', `Can't find element with ID "${maybeElement}"`); } element = maybeElement; } else { element = arg0; } if (backend === Renderer.Backends.CANVAS) { if (!isHTMLCanvas(element)) { throw new RuntimeError('BadElement', 'CANVAS context requires an HTMLCanvasElement.'); } const context = element.getContext('2d', { willReadFrequently: true }); if (!context) { throw new RuntimeError('BadElement', "Can't get canvas context"); } this.ctx = new CanvasContext(context); } else if (backend === Renderer.Backends.SVG) { if (!isHTMLDiv(element)) { throw new RuntimeError('BadElement', 'SVG context requires an HTMLDivElement.'); } this.ctx = new SVGContext(element); } else { throw new RuntimeError('InvalidBackend', `No support for backend: ${backend}`); } } } resize(width, height) { this.ctx.resize(width, height); return this; } getContext() { return this.ctx; } } Renderer.Backends = RendererBackends; Renderer.LineEndType = RendererLineEndType; Renderer.lastContext = undefined;