UNPKG

vexflow

Version:

A JavaScript library for rendering music notation and guitar tablature.

122 lines (121 loc) 4.54 kB
import { Element } from './element.js'; import { Modifier } from './modifier.js'; import { RuntimeError } from './util.js'; class StaveHairpin extends Element { static get CATEGORY() { return "StaveHairpin"; } static FormatByTicksAndDraw(ctx, formatter, notes, type, position, options) { var _a, _b; const ppt = formatter.pixelsPerTick; if (ppt == null) { throw new RuntimeError('BadArguments', 'A valid Formatter must be provide to draw offsets by ticks.'); } const l_shift_px = ppt * ((_a = options.left_shift_ticks) !== null && _a !== void 0 ? _a : 0); const r_shift_px = ppt * ((_b = options.right_shift_ticks) !== null && _b !== void 0 ? _b : 0); const hairpin_options = { height: options.height, y_shift: options.y_shift, left_shift_px: l_shift_px, right_shift_px: r_shift_px, right_shift_ticks: 0, left_shift_ticks: 0, }; new StaveHairpin({ first_note: notes.first_note, last_note: notes.last_note, }, type) .setContext(ctx) .setRenderOptions(hairpin_options) .setPosition(position) .draw(); } constructor(notes, type) { super(); this.setNotes(notes); this.hairpin = type; this.position = Modifier.Position.BELOW; this.render_options = { height: 10, y_shift: 0, left_shift_px: 0, right_shift_px: 0, right_shift_ticks: 0, left_shift_ticks: 0, }; } setPosition(position) { if (position === Modifier.Position.ABOVE || position === Modifier.Position.BELOW) { this.position = position; } return this; } setRenderOptions(options) { if (options.height != null && options.y_shift != null && options.left_shift_px != null && options.right_shift_px != null) { this.render_options = options; } return this; } setNotes(notes) { if (!notes.first_note && !notes.last_note) { throw new RuntimeError('BadArguments', 'Hairpin needs to have either first_note or last_note set.'); } this.notes = notes; this.first_note = notes.first_note; this.last_note = notes.last_note; return this; } renderHairpin(params) { const ctx = this.checkContext(); let dis = this.render_options.y_shift + 20; let y_shift = params.first_y; if (this.position === Modifier.Position.ABOVE) { dis = -dis + 30; y_shift = params.first_y - params.staff_height; } const l_shift = this.render_options.left_shift_px; const r_shift = this.render_options.right_shift_px; ctx.beginPath(); switch (this.hairpin) { case StaveHairpin.type.CRESC: ctx.moveTo(params.last_x + r_shift, y_shift + dis); ctx.lineTo(params.first_x + l_shift, y_shift + this.render_options.height / 2 + dis); ctx.lineTo(params.last_x + r_shift, y_shift + this.render_options.height + dis); break; case StaveHairpin.type.DECRESC: ctx.moveTo(params.first_x + l_shift, y_shift + dis); ctx.lineTo(params.last_x + r_shift, y_shift + this.render_options.height / 2 + dis); ctx.lineTo(params.first_x + l_shift, y_shift + this.render_options.height + dis); break; default: break; } ctx.stroke(); ctx.closePath(); } draw() { this.checkContext(); this.setRendered(); const firstNote = this.first_note; const lastNote = this.last_note; if (!firstNote || !lastNote) throw new RuntimeError('NoNote', 'Notes required to draw'); const start = firstNote.getModifierStartXY(this.position, 0); const end = lastNote.getModifierStartXY(this.position, 0); this.renderHairpin({ first_x: start.x, last_x: end.x, first_y: firstNote.checkStave().getY() + firstNote.checkStave().getHeight(), last_y: lastNote.checkStave().getY() + lastNote.checkStave().getHeight(), staff_height: firstNote.checkStave().getHeight(), }); } } StaveHairpin.type = { CRESC: 1, DECRESC: 2, }; export { StaveHairpin };