UNPKG

vexflow

Version:

A JavaScript library for rendering music notation and guitar tablature.

135 lines (134 loc) 5.4 kB
import { Element } from './element.js'; import { Tables } from './tables.js'; import { log, RuntimeError } from './util.js'; function L(...args) { if (Stem.DEBUG) log('Vex.Flow.Stem', args); } class Stem extends Element { static get CATEGORY() { return "Stem"; } static get UP() { return 1; } static get DOWN() { return -1; } static get WIDTH() { return Tables.STEM_WIDTH; } static get HEIGHT() { return Tables.STEM_HEIGHT; } constructor(options) { super(); this.stem_up_y_offset = 0; this.stem_down_y_offset = 0; this.stem_up_y_base_offset = 0; this.stem_down_y_base_offset = 0; this.x_begin = (options === null || options === void 0 ? void 0 : options.x_begin) || 0; this.x_end = (options === null || options === void 0 ? void 0 : options.x_end) || 0; this.y_top = (options === null || options === void 0 ? void 0 : options.y_top) || 0; this.y_bottom = (options === null || options === void 0 ? void 0 : options.y_bottom) || 0; this.stem_extension = (options === null || options === void 0 ? void 0 : options.stem_extension) || 0; this.stem_direction = (options === null || options === void 0 ? void 0 : options.stem_direction) || 0; this.hide = (options === null || options === void 0 ? void 0 : options.hide) || false; this.isStemlet = (options === null || options === void 0 ? void 0 : options.isStemlet) || false; this.stemletHeight = (options === null || options === void 0 ? void 0 : options.stemletHeight) || 0; this.renderHeightAdjustment = 0; this.setOptions(options); } setOptions(options) { this.stem_up_y_offset = (options === null || options === void 0 ? void 0 : options.stem_up_y_offset) || 0; this.stem_down_y_offset = (options === null || options === void 0 ? void 0 : options.stem_down_y_offset) || 0; this.stem_up_y_base_offset = (options === null || options === void 0 ? void 0 : options.stem_up_y_base_offset) || 0; this.stem_down_y_base_offset = (options === null || options === void 0 ? void 0 : options.stem_down_y_base_offset) || 0; } setNoteHeadXBounds(x_begin, x_end) { this.x_begin = x_begin; this.x_end = x_end; return this; } setDirection(direction) { this.stem_direction = direction; } setExtension(ext) { this.stem_extension = ext; } getExtension() { return this.stem_extension; } setYBounds(y_top, y_bottom) { this.y_top = y_top; this.y_bottom = y_bottom; } getHeight() { const y_offset = this.stem_direction === Stem.UP ? this.stem_up_y_offset : this.stem_down_y_offset; const unsigned_height = this.y_bottom - this.y_top + (Stem.HEIGHT - y_offset + this.stem_extension); return unsigned_height * this.stem_direction; } getBoundingBox() { throw new RuntimeError('NotImplemented', 'getBoundingBox() not implemented.'); } getExtents() { const isStemUp = this.stem_direction === Stem.UP; const ys = [this.y_top, this.y_bottom]; const stemHeight = Stem.HEIGHT + this.stem_extension; const innerMostNoteheadY = (isStemUp ? Math.min : Math.max)(...ys); const outerMostNoteheadY = (isStemUp ? Math.max : Math.min)(...ys); const stemTipY = innerMostNoteheadY + stemHeight * -this.stem_direction; return { topY: stemTipY, baseY: outerMostNoteheadY }; } setVisibility(isVisible) { this.hide = !isVisible; return this; } setStemlet(isStemlet, stemletHeight) { this.isStemlet = isStemlet; this.stemletHeight = stemletHeight; return this; } adjustHeightForFlag() { this.renderHeightAdjustment = Tables.currentMusicFont().lookupMetric('stem.heightAdjustmentForFlag', -3); } adjustHeightForBeam() { this.renderHeightAdjustment = -Stem.WIDTH / 2; } draw() { this.setRendered(); if (this.hide) return; const ctx = this.checkContext(); let stem_x; let stem_y; const stem_direction = this.stem_direction; let y_base_offset = 0; if (stem_direction === Stem.DOWN) { stem_x = this.x_begin; stem_y = this.y_top + this.stem_down_y_offset; y_base_offset = this.stem_down_y_base_offset; } else { stem_x = this.x_end; stem_y = this.y_bottom - this.stem_up_y_offset; y_base_offset = this.stem_up_y_base_offset; } const stemHeight = this.getHeight(); L('Rendering stem - ', 'Top Y: ', this.y_top, 'Bottom Y: ', this.y_bottom); const stemletYOffset = this.isStemlet ? stemHeight - this.stemletHeight * this.stem_direction : 0; ctx.save(); this.applyStyle(); ctx.openGroup('stem', this.getAttribute('id'), { pointerBBox: true }); ctx.beginPath(); ctx.setLineWidth(Stem.WIDTH); ctx.moveTo(stem_x, stem_y - stemletYOffset + y_base_offset); ctx.lineTo(stem_x, stem_y - stemHeight - this.renderHeightAdjustment * stem_direction); ctx.stroke(); ctx.closeGroup(); this.restoreStyle(); ctx.restore(); } } Stem.DEBUG = false; export { Stem };