vexflow
Version:
A JavaScript library for rendering music notation and guitar tablature
1,096 lines (713 loc) • 37.2 kB
HTML
<html>
<head>
<title>staveline.js</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="stylesheet" media="all" href="public/stylesheets/normalize.css" />
<link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
<div class="container">
<div class="page">
<div class="header">
<h1>staveline.js</h1>
<div class="toc">
<h3>Table of Contents</h3>
<ol>
<li>
<a class="source" href="accidental.html">
accidental.js
</a>
</li>
<li>
<a class="source" href="annotation.html">
annotation.js
</a>
</li>
<li>
<a class="source" href="articulation.html">
articulation.js
</a>
</li>
<li>
<a class="source" href="barnote.html">
barnote.js
</a>
</li>
<li>
<a class="source" href="beam.html">
beam.js
</a>
</li>
<li>
<a class="source" href="bend.html">
bend.js
</a>
</li>
<li>
<a class="source" href="boundingbox.html">
boundingbox.js
</a>
</li>
<li>
<a class="source" href="boundingboxcomputation.html">
boundingboxcomputation.js
</a>
</li>
<li>
<a class="source" href="canvascontext.html">
canvascontext.js
</a>
</li>
<li>
<a class="source" href="clef.html">
clef.js
</a>
</li>
<li>
<a class="source" href="clefnote.html">
clefnote.js
</a>
</li>
<li>
<a class="source" href="crescendo.html">
crescendo.js
</a>
</li>
<li>
<a class="source" href="curve.html">
curve.js
</a>
</li>
<li>
<a class="source" href="dot.html">
dot.js
</a>
</li>
<li>
<a class="source" href="easyscore.html">
easyscore.js
</a>
</li>
<li>
<a class="source" href="element.html">
element.js
</a>
</li>
<li>
<a class="source" href="factory.html">
factory.js
</a>
</li>
<li>
<a class="source" href="formatter.html">
formatter.js
</a>
</li>
<li>
<a class="source" href="fraction.html">
fraction.js
</a>
</li>
<li>
<a class="source" href="frethandfinger.html">
frethandfinger.js
</a>
</li>
<li>
<a class="source" href="ghostnote.html">
ghostnote.js
</a>
</li>
<li>
<a class="source" href="glyph.html">
glyph.js
</a>
</li>
<li>
<a class="source" href="glyphnote.html">
glyphnote.js
</a>
</li>
<li>
<a class="source" href="gracenote.html">
gracenote.js
</a>
</li>
<li>
<a class="source" href="gracenotegroup.html">
gracenotegroup.js
</a>
</li>
<li>
<a class="source" href="gracetabnote.html">
gracetabnote.js
</a>
</li>
<li>
<a class="source" href="index.html">
index.js
</a>
</li>
<li>
<a class="source" href="keymanager.html">
keymanager.js
</a>
</li>
<li>
<a class="source" href="keysignature.html">
keysignature.js
</a>
</li>
<li>
<a class="source" href="keysignote.html">
keysignote.js
</a>
</li>
<li>
<a class="source" href="modifier.html">
modifier.js
</a>
</li>
<li>
<a class="source" href="modifiercontext.html">
modifiercontext.js
</a>
</li>
<li>
<a class="source" href="multimeasurerest.html">
multimeasurerest.js
</a>
</li>
<li>
<a class="source" href="music.html">
music.js
</a>
</li>
<li>
<a class="source" href="note.html">
note.js
</a>
</li>
<li>
<a class="source" href="notehead.html">
notehead.js
</a>
</li>
<li>
<a class="source" href="notesubgroup.html">
notesubgroup.js
</a>
</li>
<li>
<a class="source" href="ornament.html">
ornament.js
</a>
</li>
<li>
<a class="source" href="parser.html">
parser.js
</a>
</li>
<li>
<a class="source" href="pedalmarking.html">
pedalmarking.js
</a>
</li>
<li>
<a class="source" href="raphaelcontext.html">
raphaelcontext.js
</a>
</li>
<li>
<a class="source" href="registry.html">
registry.js
</a>
</li>
<li>
<a class="source" href="renderer.html">
renderer.js
</a>
</li>
<li>
<a class="source" href="repeatnote.html">
repeatnote.js
</a>
</li>
<li>
<a class="source" href="smufl.html">
smufl.js
</a>
</li>
<li>
<a class="source" href="stave.html">
stave.js
</a>
</li>
<li>
<a class="source" href="stavebarline.html">
stavebarline.js
</a>
</li>
<li>
<a class="source" href="staveconnector.html">
staveconnector.js
</a>
</li>
<li>
<a class="source" href="stavehairpin.html">
stavehairpin.js
</a>
</li>
<li>
<a class="source" href="staveline.html">
staveline.js
</a>
</li>
<li>
<a class="source" href="stavemodifier.html">
stavemodifier.js
</a>
</li>
<li>
<a class="source" href="stavenote.html">
stavenote.js
</a>
</li>
<li>
<a class="source" href="staverepetition.html">
staverepetition.js
</a>
</li>
<li>
<a class="source" href="stavesection.html">
stavesection.js
</a>
</li>
<li>
<a class="source" href="stavetempo.html">
stavetempo.js
</a>
</li>
<li>
<a class="source" href="stavetext.html">
stavetext.js
</a>
</li>
<li>
<a class="source" href="stavetie.html">
stavetie.js
</a>
</li>
<li>
<a class="source" href="stavevolta.html">
stavevolta.js
</a>
</li>
<li>
<a class="source" href="stem.html">
stem.js
</a>
</li>
<li>
<a class="source" href="stemmablenote.html">
stemmablenote.js
</a>
</li>
<li>
<a class="source" href="stringnumber.html">
stringnumber.js
</a>
</li>
<li>
<a class="source" href="strokes.html">
strokes.js
</a>
</li>
<li>
<a class="source" href="svgcontext.html">
svgcontext.js
</a>
</li>
<li>
<a class="source" href="system.html">
system.js
</a>
</li>
<li>
<a class="source" href="tables.html">
tables.js
</a>
</li>
<li>
<a class="source" href="tabnote.html">
tabnote.js
</a>
</li>
<li>
<a class="source" href="tabslide.html">
tabslide.js
</a>
</li>
<li>
<a class="source" href="tabstave.html">
tabstave.js
</a>
</li>
<li>
<a class="source" href="tabtie.html">
tabtie.js
</a>
</li>
<li>
<a class="source" href="textbracket.html">
textbracket.js
</a>
</li>
<li>
<a class="source" href="textdynamics.html">
textdynamics.js
</a>
</li>
<li>
<a class="source" href="textnote.html">
textnote.js
</a>
</li>
<li>
<a class="source" href="tickable.html">
tickable.js
</a>
</li>
<li>
<a class="source" href="tickcontext.html">
tickcontext.js
</a>
</li>
<li>
<a class="source" href="timesignature.html">
timesignature.js
</a>
</li>
<li>
<a class="source" href="timesignote.html">
timesignote.js
</a>
</li>
<li>
<a class="source" href="tremolo.html">
tremolo.js
</a>
</li>
<li>
<a class="source" href="tuning.html">
tuning.js
</a>
</li>
<li>
<a class="source" href="tuplet.html">
tuplet.js
</a>
</li>
<li>
<a class="source" href="vex.html">
vex.js
</a>
</li>
<li>
<a class="source" href="vibrato.html">
vibrato.js
</a>
</li>
<li>
<a class="source" href="vibratobracket.html">
vibratobracket.js
</a>
</li>
<li>
<a class="source" href="voice.html">
voice.js
</a>
</li>
<li>
<a class="source" href="voicegroup.html">
voicegroup.js
</a>
</li>
</ol>
</div>
</div>
<p><a href="http://vexflow.com">VexFlow</a> - Copyright (c) Mohit Muthanna 2010.</p>
<h2 id="description">Description</h2>
<p>This file implements <code>StaveLine</code> which are simply lines that connect
two notes. This object is highly configurable, see the <code>render_options</code>.
A simple line is often used for notating glissando articulations, but you
can format a <code>StaveLine</code> with arrows or colors for more pedagogical
purposes, such as diagrams.</p>
<div class='highlight'><pre><span class="hljs-keyword">import</span> { Vex } <span class="hljs-keyword">from</span> <span class="hljs-string">'./vex'</span>;
<span class="hljs-keyword">import</span> { Element } <span class="hljs-keyword">from</span> <span class="hljs-string">'./element'</span>;
<span class="hljs-keyword">import</span> { Flow } <span class="hljs-keyword">from</span> <span class="hljs-string">'./tables'</span>;</pre></div>
<p>Attribution: Arrow rendering implementations based off of
Patrick Horgan’s article, “Drawing lines and arcs with
arrow heads on HTML5 Canvas”</p>
<p>Draw an arrow head that connects between 3 coordinates</p>
<div class='highlight'><pre><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">drawArrowHead</span>(<span class="hljs-params">ctx, x0, y0, x1, y1, x2, y2</span>) </span>{</pre></div>
<p>all cases do this.</p>
<div class='highlight'><pre> ctx.beginPath();
ctx.moveTo(x0, y0);
ctx.lineTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.lineTo(x0, y0);
ctx.closePath();
ctx.fill();
}</pre></div>
<p>Helper function to draw a line with arrow heads</p>
<div class='highlight'><pre><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">drawArrowLine</span>(<span class="hljs-params">ctx, point1, point2, config</span>) </span>{
<span class="hljs-keyword">const</span> both_arrows = config.draw_start_arrow && config.draw_end_arrow;
<span class="hljs-keyword">const</span> x1 = point1.x;
<span class="hljs-keyword">const</span> y1 = point1.y;
<span class="hljs-keyword">const</span> x2 = point2.x;
<span class="hljs-keyword">const</span> y2 = point2.y;</pre></div>
<p>For ends with arrow we actually want to stop before we get to the arrow
so that wide lines won’t put a flat end on the arrow.</p>
<div class='highlight'><pre> <span class="hljs-keyword">const</span> distance = <span class="hljs-built_in">Math</span>.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
<span class="hljs-keyword">const</span> ratio = (distance - config.arrowhead_length / <span class="hljs-number">3</span>) / distance;
<span class="hljs-keyword">let</span> end_x;
<span class="hljs-keyword">let</span> end_y;
<span class="hljs-keyword">let</span> start_x;
<span class="hljs-keyword">let</span> start_y;
<span class="hljs-keyword">if</span> (config.draw_end_arrow || both_arrows) {
end_x = <span class="hljs-built_in">Math</span>.round(x1 + (x2 - x1) * ratio);
end_y = <span class="hljs-built_in">Math</span>.round(y1 + (y2 - y1) * ratio);
} <span class="hljs-keyword">else</span> {
end_x = x2;
end_y = y2;
}
<span class="hljs-keyword">if</span> (config.draw_start_arrow || both_arrows) {
start_x = x1 + (x2 - x1) * (<span class="hljs-number">1</span> - ratio);
start_y = y1 + (y2 - y1) * (<span class="hljs-number">1</span> - ratio);
} <span class="hljs-keyword">else</span> {
start_x = x1;
start_y = y1;
}
<span class="hljs-keyword">if</span> (config.color) {
ctx.setStrokeStyle(config.color);
ctx.setFillStyle(config.color);
}</pre></div>
<p>Draw the shaft of the arrow</p>
<div class='highlight'><pre> ctx.beginPath();
ctx.moveTo(start_x, start_y);
ctx.lineTo(end_x, end_y);
ctx.stroke();
ctx.closePath();</pre></div>
<p>calculate the angle of the line</p>
<div class='highlight'><pre> <span class="hljs-keyword">const</span> line_angle = <span class="hljs-built_in">Math</span>.atan2(y2 - y1, x2 - x1);</pre></div>
<p>h is the line length of a side of the arrow head</p>
<div class='highlight'><pre> <span class="hljs-keyword">const</span> h = <span class="hljs-built_in">Math</span>.abs(config.arrowhead_length / <span class="hljs-built_in">Math</span>.cos(config.arrowhead_angle));
<span class="hljs-keyword">let</span> angle1;
<span class="hljs-keyword">let</span> angle2;
<span class="hljs-keyword">let</span> top_x;
<span class="hljs-keyword">let</span> top_y;
<span class="hljs-keyword">let</span> bottom_x;
<span class="hljs-keyword">let</span> bottom_y;
<span class="hljs-keyword">if</span> (config.draw_end_arrow || both_arrows) {
angle1 = line_angle + <span class="hljs-built_in">Math</span>.PI + config.arrowhead_angle;
top_x = x2 + <span class="hljs-built_in">Math</span>.cos(angle1) * h;
top_y = y2 + <span class="hljs-built_in">Math</span>.sin(angle1) * h;
angle2 = line_angle + <span class="hljs-built_in">Math</span>.PI - config.arrowhead_angle;
bottom_x = x2 + <span class="hljs-built_in">Math</span>.cos(angle2) * h;
bottom_y = y2 + <span class="hljs-built_in">Math</span>.sin(angle2) * h;
drawArrowHead(ctx, top_x, top_y, x2, y2, bottom_x, bottom_y);
}
<span class="hljs-keyword">if</span> (config.draw_start_arrow || both_arrows) {
angle1 = line_angle + config.arrowhead_angle;
top_x = x1 + <span class="hljs-built_in">Math</span>.cos(angle1) * h;
top_y = y1 + <span class="hljs-built_in">Math</span>.sin(angle1) * h;
angle2 = line_angle - config.arrowhead_angle;
bottom_x = x1 + <span class="hljs-built_in">Math</span>.cos(angle2) * h;
bottom_y = y1 + <span class="hljs-built_in">Math</span>.sin(angle2) * h;
drawArrowHead(ctx, top_x, top_y, x1, y1, bottom_x, bottom_y);
}
}
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StaveLine</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Element</span> </span>{</pre></div>
<p>Text Positioning</p>
<div class='highlight'><pre> <span class="hljs-keyword">static</span> get TextVerticalPosition() {
<span class="hljs-keyword">return</span> {
<span class="hljs-attr">TOP</span>: <span class="hljs-number">1</span>,
<span class="hljs-attr">BOTTOM</span>: <span class="hljs-number">2</span>,
};
}
<span class="hljs-keyword">static</span> get TextJustification() {
<span class="hljs-keyword">return</span> {
<span class="hljs-attr">LEFT</span>: <span class="hljs-number">1</span>,
<span class="hljs-attr">CENTER</span>: <span class="hljs-number">2</span>,
<span class="hljs-attr">RIGHT</span>: <span class="hljs-number">3</span>,
};
}</pre></div>
<p>Initialize the StaveLine with the given <code>notes</code>.</p>
<p><code>notes</code> is a struct that has:</p>
<pre><code> {
<span class="hljs-attr">first_note</span>: Note,
<span class="hljs-attr">last_note</span>: Note,
<span class="hljs-attr">first_indices</span>: [n1, n2, n3],
<span class="hljs-attr">last_indices</span>: [n1, n2, n3]
}</code></pre>
<div class='highlight'><pre> <span class="hljs-keyword">constructor</span>(notes) {
<span class="hljs-keyword">super</span>();
<span class="hljs-keyword">this</span>.setAttribute(<span class="hljs-string">'type'</span>, <span class="hljs-string">'StaveLine'</span>);
<span class="hljs-keyword">this</span>.notes = notes;
<span class="hljs-keyword">this</span>.text = <span class="hljs-string">''</span>;
<span class="hljs-keyword">this</span>.font = {
<span class="hljs-attr">family</span>: <span class="hljs-string">'Arial'</span>,
<span class="hljs-attr">size</span>: <span class="hljs-number">10</span>,
<span class="hljs-attr">weight</span>: <span class="hljs-string">''</span>,
};
<span class="hljs-keyword">this</span>.render_options = {</pre></div>
<p>Space to add to the left or the right</p>
<div class='highlight'><pre> padding_left: <span class="hljs-number">4</span>,
<span class="hljs-attr">padding_right</span>: <span class="hljs-number">3</span>,</pre></div>
<p>The width of the line in pixels</p>
<div class='highlight'><pre> line_width: <span class="hljs-number">1</span>,</pre></div>
<p>An array of line/space lengths. Unsupported with Raphael (SVG)</p>
<div class='highlight'><pre> line_dash: <span class="hljs-literal">null</span>,</pre></div>
<p>Can draw rounded line end, instead of a square. Unsupported with Raphael (SVG)</p>
<div class='highlight'><pre> rounded_end: <span class="hljs-literal">true</span>,</pre></div>
<p>The color of the line and arrowheads</p>
<div class='highlight'><pre> color: <span class="hljs-literal">null</span>,</pre></div>
<p>Flags to draw arrows on each end of the line</p>
<div class='highlight'><pre> draw_start_arrow: <span class="hljs-literal">false</span>,
<span class="hljs-attr">draw_end_arrow</span>: <span class="hljs-literal">false</span>,</pre></div>
<p>The length of the arrowhead sides</p>
<div class='highlight'><pre> arrowhead_length: <span class="hljs-number">10</span>,</pre></div>
<p>The angle of the arrowhead</p>
<div class='highlight'><pre> arrowhead_angle: <span class="hljs-built_in">Math</span>.PI / <span class="hljs-number">8</span>,</pre></div>
<p>The position of the text</p>
<div class='highlight'><pre> text_position_vertical: StaveLine.TextVerticalPosition.TOP,
<span class="hljs-attr">text_justification</span>: StaveLine.TextJustification.CENTER,
};
<span class="hljs-keyword">this</span>.setNotes(notes);
}</pre></div>
<p>Set the font for the <code>StaveLine</code> text</p>
<div class='highlight'><pre> setFont(font) { <span class="hljs-keyword">this</span>.font = font; <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>; }</pre></div>
<p>The the annotation for the <code>StaveLine</code></p>
<div class='highlight'><pre> setText(text) { <span class="hljs-keyword">this</span>.text = text; <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>; }</pre></div>
<p>Set the notes for the <code>StaveLine</code></p>
<div class='highlight'><pre> setNotes(notes) {
<span class="hljs-keyword">if</span> (!notes.first_note && !notes.last_note) {
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Vex.RuntimeError(
<span class="hljs-string">'BadArguments'</span>, <span class="hljs-string">'Notes needs to have either first_note or last_note set.'</span>
);
}
<span class="hljs-keyword">if</span> (!notes.first_indices) notes.first_indices = [<span class="hljs-number">0</span>];
<span class="hljs-keyword">if</span> (!notes.last_indices) notes.last_indices = [<span class="hljs-number">0</span>];
<span class="hljs-keyword">if</span> (notes.first_indices.length !== notes.last_indices.length) {
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Vex.RuntimeError(
<span class="hljs-string">'BadArguments'</span>, <span class="hljs-string">'Connected notes must have similar index sizes'</span>
);
}</pre></div>
<p>Success. Lets grab ‘em notes.</p>
<div class='highlight'><pre> <span class="hljs-keyword">this</span>.first_note = notes.first_note;
<span class="hljs-keyword">this</span>.first_indices = notes.first_indices;
<span class="hljs-keyword">this</span>.last_note = notes.last_note;
<span class="hljs-keyword">this</span>.last_indices = notes.last_indices;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}</pre></div>
<p>Apply the style of the <code>StaveLine</code> to the context</p>
<div class='highlight'><pre> applyLineStyle() {
<span class="hljs-keyword">const</span> ctx = <span class="hljs-keyword">this</span>.checkContext();
<span class="hljs-keyword">const</span> render_options = <span class="hljs-keyword">this</span>.render_options;
<span class="hljs-keyword">if</span> (render_options.line_dash) {
ctx.setLineDash(render_options.line_dash);
}
<span class="hljs-keyword">if</span> (render_options.line_width) {
ctx.setLineWidth(render_options.line_width);
}
<span class="hljs-keyword">if</span> (render_options.rounded_end) {
ctx.setLineCap(<span class="hljs-string">'round'</span>);
} <span class="hljs-keyword">else</span> {
ctx.setLineCap(<span class="hljs-string">'square'</span>);
}
}</pre></div>
<p>Apply the text styling to the context</p>
<div class='highlight'><pre> applyFontStyle() {
<span class="hljs-keyword">const</span> ctx = <span class="hljs-keyword">this</span>.checkContext();
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.font) {
ctx.setFont(<span class="hljs-keyword">this</span>.font.family, <span class="hljs-keyword">this</span>.font.size, <span class="hljs-keyword">this</span>.font.weight);
}
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.render_options.color) {
ctx.setStrokeStyle(<span class="hljs-keyword">this</span>.render_options.color);
ctx.setFillStyle(<span class="hljs-keyword">this</span>.render_options.color);
}
}</pre></div>
<p>Renders the <code>StaveLine</code> on the context</p>
<div class='highlight'><pre> draw() {
<span class="hljs-keyword">const</span> ctx = <span class="hljs-keyword">this</span>.checkContext();
<span class="hljs-keyword">this</span>.setRendered();
<span class="hljs-keyword">const</span> first_note = <span class="hljs-keyword">this</span>.first_note;
<span class="hljs-keyword">const</span> last_note = <span class="hljs-keyword">this</span>.last_note;
<span class="hljs-keyword">const</span> render_options = <span class="hljs-keyword">this</span>.render_options;
ctx.save();
<span class="hljs-keyword">this</span>.applyLineStyle();</pre></div>
<p>Cycle through each set of indices and draw lines</p>
<div class='highlight'><pre> <span class="hljs-keyword">let</span> start_position;
<span class="hljs-keyword">let</span> end_position;
<span class="hljs-keyword">this</span>.first_indices.forEach(<span class="hljs-function">(<span class="hljs-params">first_index, i</span>) =></span> {
<span class="hljs-keyword">const</span> last_index = <span class="hljs-keyword">this</span>.last_indices[i];</pre></div>
<p>Get initial coordinates for the start/end of the line</p>
<div class='highlight'><pre> start_position = first_note.getModifierStartXY(<span class="hljs-number">2</span>, first_index);
end_position = last_note.getModifierStartXY(<span class="hljs-number">1</span>, last_index);
<span class="hljs-keyword">const</span> upwards_slope = start_position.y > end_position.y;</pre></div>
<p>Adjust <code>x</code> coordinates for modifiers</p>
<div class='highlight'><pre> start_position.x += first_note.getMetrics().modRightPx + render_options.padding_left;
end_position.x -= last_note.getMetrics().modLeftPx + render_options.padding_right;</pre></div>
<p>Adjust first <code>x</code> coordinates for displacements</p>
<div class='highlight'><pre> <span class="hljs-keyword">const</span> notehead_width = first_note.getGlyph().getWidth();
<span class="hljs-keyword">const</span> first_displaced = first_note.getKeyProps()[first_index].displaced;
<span class="hljs-keyword">if</span> (first_displaced && first_note.getStemDirection() === <span class="hljs-number">1</span>) {
start_position.x += notehead_width + render_options.padding_left;
}</pre></div>
<p>Adjust last <code>x</code> coordinates for displacements</p>
<div class='highlight'><pre> <span class="hljs-keyword">const</span> last_displaced = last_note.getKeyProps()[last_index].displaced;
<span class="hljs-keyword">if</span> (last_displaced && last_note.getStemDirection() === <span class="hljs-number">-1</span>) {
end_position.x -= notehead_width + render_options.padding_right;
}</pre></div>
<p>Adjust y position better if it’s not coming from the center of the note</p>
<div class='highlight'><pre> start_position.y += upwards_slope ? <span class="hljs-number">-3</span> : <span class="hljs-number">1</span>;
end_position.y += upwards_slope ? <span class="hljs-number">2</span> : <span class="hljs-number">0</span>;
drawArrowLine(ctx, start_position, end_position, <span class="hljs-keyword">this</span>.render_options);
});
ctx.restore();</pre></div>
<p>Determine the x coordinate where to start the text</p>
<div class='highlight'><pre> <span class="hljs-keyword">const</span> text_width = ctx.measureText(<span class="hljs-keyword">this</span>.text).width;
<span class="hljs-keyword">const</span> justification = render_options.text_justification;
<span class="hljs-keyword">let</span> x = <span class="hljs-number">0</span>;
<span class="hljs-keyword">if</span> (justification === StaveLine.TextJustification.LEFT) {
x = start_position.x;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (justification === StaveLine.TextJustification.CENTER) {
<span class="hljs-keyword">const</span> delta_x = (end_position.x - start_position.x);
<span class="hljs-keyword">const</span> center_x = (delta_x / <span class="hljs-number">2</span>) + start_position.x;
x = center_x - (text_width / <span class="hljs-number">2</span>);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (justification === StaveLine.TextJustification.RIGHT) {
x = end_position.x - text_width;
}</pre></div>
<p>Determine the y value to start the text</p>
<div class='highlight'><pre> <span class="hljs-keyword">let</span> y;
<span class="hljs-keyword">const</span> vertical_position = render_options.text_position_vertical;
<span class="hljs-keyword">if</span> (vertical_position === StaveLine.TextVerticalPosition.TOP) {
y = first_note.getStave().getYForTopText();
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (vertical_position === StaveLine.TextVerticalPosition.BOTTOM) {
y = first_note.getStave().getYForBottomText(Flow.TEXT_HEIGHT_OFFSET_HACK);
}</pre></div>
<p>Draw the text</p>
<div class='highlight'><pre> ctx.save();
<span class="hljs-keyword">this</span>.applyFontStyle();
ctx.fillText(<span class="hljs-keyword">this</span>.text, x, y);
ctx.restore();
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
}</pre></div>
<div class="fleur">h</div>
</div>
</div>
</body>
</html>