vexflow
Version:
A JavaScript library for rendering music notation and guitar tablature
1,064 lines (786 loc) • 40.3 kB
HTML
<html>
<head>
<title>raphaelcontext.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>raphaelcontext.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>A rendering context for the Raphael backend.</p>
<h2 id="warning-deprecated-for-svgcontext">Warning: Deprecated for SVGContext</h2>
<p>Except in instances where SVG support for IE < 9.0 is
needed, SVGContext is recommended.</p>
<div class='highlight'><pre>
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RaphaelContext</span> </span>{
<span class="hljs-keyword">constructor</span>(element) {
<span class="hljs-keyword">this</span>.element = element;
<span class="hljs-keyword">this</span>.paper = Raphael(element); <span class="hljs-comment">// eslint-disable-line</span>
<span class="hljs-keyword">this</span>.path = <span class="hljs-string">''</span>;
<span class="hljs-keyword">this</span>.pen = { <span class="hljs-attr">x</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">0</span> };
<span class="hljs-keyword">this</span>.lineWidth = <span class="hljs-number">1.0</span>;
<span class="hljs-keyword">this</span>.state = {
<span class="hljs-attr">scale</span>: { <span class="hljs-attr">x</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">1</span> },
<span class="hljs-attr">font_family</span>: <span class="hljs-string">'Arial'</span>,
<span class="hljs-attr">font_size</span>: <span class="hljs-number">8</span>,
<span class="hljs-attr">font_weight</span>: <span class="hljs-number">800</span>,
};
<span class="hljs-keyword">this</span>.attributes = {
<span class="hljs-string">'stroke-width'</span>: <span class="hljs-number">0.3</span>,
<span class="hljs-string">'fill'</span>: <span class="hljs-string">'black'</span>,
<span class="hljs-string">'stroke'</span>: <span class="hljs-string">'black'</span>,
<span class="hljs-string">'font'</span>: <span class="hljs-string">'10pt Arial'</span>,
};
<span class="hljs-keyword">this</span>.background_attributes = {
<span class="hljs-string">'stroke-width'</span>: <span class="hljs-number">0</span>,
<span class="hljs-string">'fill'</span>: <span class="hljs-string">'white'</span>,
<span class="hljs-string">'stroke'</span>: <span class="hljs-string">'white'</span>,
<span class="hljs-string">'font'</span>: <span class="hljs-string">'10pt Arial'</span>,
};
<span class="hljs-keyword">this</span>.shadow_attributes = {
<span class="hljs-attr">width</span>: <span class="hljs-number">0</span>,
<span class="hljs-attr">color</span>: <span class="hljs-string">'black'</span>,
};
<span class="hljs-keyword">this</span>.state_stack = [];
}</pre></div>
<p>Containers not implemented</p>
<div class='highlight'><pre> openGroup() {}
closeGroup() {}
add() {}
setFont(family, size, weight) {
<span class="hljs-keyword">this</span>.state.font_family = family;
<span class="hljs-keyword">this</span>.state.font_size = size;
<span class="hljs-keyword">this</span>.state.font_weight = weight;
<span class="hljs-keyword">this</span>.attributes.font = (<span class="hljs-keyword">this</span>.state.font_weight || <span class="hljs-string">''</span>) + <span class="hljs-string">' '</span> +
(<span class="hljs-keyword">this</span>.state.font_size * <span class="hljs-keyword">this</span>.state.scale.x) + <span class="hljs-string">'pt '</span> +
<span class="hljs-keyword">this</span>.state.font_family;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
setRawFont(font) {
<span class="hljs-keyword">this</span>.attributes.font = font;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
setFillStyle(style) {
<span class="hljs-keyword">this</span>.attributes.fill = style;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
setBackgroundFillStyle(style) {
<span class="hljs-keyword">this</span>.background_attributes.fill = style;
<span class="hljs-keyword">this</span>.background_attributes.stroke = style;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
setStrokeStyle(style) {
<span class="hljs-keyword">this</span>.attributes.stroke = style;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
setShadowColor(style) {
<span class="hljs-keyword">this</span>.shadow_attributes.color = style;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
setShadowBlur(blur) {
<span class="hljs-keyword">this</span>.shadow_attributes.width = blur;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
setLineWidth(width) {
<span class="hljs-keyword">this</span>.attributes[<span class="hljs-string">'stroke-width'</span>] = width;
<span class="hljs-keyword">this</span>.lineWidth = width;
}</pre></div>
<p>Empty because there is no equivalent in SVG</p>
<div class='highlight'><pre> setLineDash() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>; }
setLineCap() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>; }
scale(x, y) {
<span class="hljs-keyword">this</span>.state.scale = { x, y };</pre></div>
<p>The scale() method is deprecated as of Raphael.JS 2.0, and
can no longer be used as an option in an Element.attr() call.
It is preserved here for users running earlier versions of
Raphael.JS, though it has no effect on the SVG output in
Raphael 2 and higher.</p>
<div class='highlight'><pre> <span class="hljs-keyword">this</span>.attributes.transform = <span class="hljs-string">'S'</span> + x + <span class="hljs-string">','</span> + y + <span class="hljs-string">',0,0'</span>;
<span class="hljs-keyword">this</span>.attributes.scale = x + <span class="hljs-string">','</span> + y + <span class="hljs-string">',0,0'</span>;
<span class="hljs-keyword">this</span>.attributes.font = <span class="hljs-keyword">this</span>.state.font_size * <span class="hljs-keyword">this</span>.state.scale.x + <span class="hljs-string">'pt '</span> +
<span class="hljs-keyword">this</span>.state.font_family;
<span class="hljs-keyword">this</span>.background_attributes.transform = <span class="hljs-string">'S'</span> + x + <span class="hljs-string">','</span> + y + <span class="hljs-string">',0,0'</span>;
<span class="hljs-keyword">this</span>.background_attributes.font = <span class="hljs-keyword">this</span>.state.font_size *
<span class="hljs-keyword">this</span>.state.scale.x + <span class="hljs-string">'pt '</span> +
<span class="hljs-keyword">this</span>.state.font_family;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
clear() { <span class="hljs-keyword">this</span>.paper.clear(); }
resize(width, height) {
<span class="hljs-keyword">this</span>.element.style.width = width;
<span class="hljs-keyword">this</span>.paper.setSize(width, height);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}</pre></div>
<p>Sets the SVG <code>viewBox</code> property, which results in auto scaling images when its container
is resized.</p>
<p>Usage: <code>ctx.setViewBox("0 0 600 400")</code></p>
<div class='highlight'><pre> setViewBox(viewBox) {
<span class="hljs-keyword">this</span>.paper.canvas.setAttribute(<span class="hljs-string">'viewBox'</span>, viewBox);
}
rect(x, y, width, height) {
<span class="hljs-keyword">if</span> (height < <span class="hljs-number">0</span>) {
y += height;
height = -height;
}
<span class="hljs-keyword">this</span>.paper.rect(x, y, width - <span class="hljs-number">0.5</span>, height - <span class="hljs-number">0.5</span>)
.attr(<span class="hljs-keyword">this</span>.attributes)
.attr(<span class="hljs-string">'fill'</span>, <span class="hljs-string">'none'</span>)
.attr(<span class="hljs-string">'stroke-width'</span>, <span class="hljs-keyword">this</span>.lineWidth);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
fillRect(x, y, width, height) {
<span class="hljs-keyword">if</span> (height < <span class="hljs-number">0</span>) {
y += height;
height = -height;
}
<span class="hljs-keyword">this</span>.paper.rect(x, y, width - <span class="hljs-number">0.5</span>, height - <span class="hljs-number">0.5</span>).attr(<span class="hljs-keyword">this</span>.attributes);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
clearRect(x, y, width, height) {
<span class="hljs-keyword">if</span> (height < <span class="hljs-number">0</span>) {
y += height;
height = -height;
}
<span class="hljs-keyword">this</span>.paper.rect(x, y, width - <span class="hljs-number">0.5</span>, height - <span class="hljs-number">0.5</span>)
.attr(<span class="hljs-keyword">this</span>.background_attributes);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
beginPath() {
<span class="hljs-keyword">this</span>.path = <span class="hljs-string">''</span>;
<span class="hljs-keyword">this</span>.pen.x = <span class="hljs-number">0</span>;
<span class="hljs-keyword">this</span>.pen.y = <span class="hljs-number">0</span>;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
moveTo(x, y) {
<span class="hljs-keyword">this</span>.path += <span class="hljs-string">'M'</span> + x + <span class="hljs-string">','</span> + y;
<span class="hljs-keyword">this</span>.pen.x = x;
<span class="hljs-keyword">this</span>.pen.y = y;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
lineTo(x, y) {
<span class="hljs-keyword">this</span>.path += <span class="hljs-string">'L'</span> + x + <span class="hljs-string">','</span> + y;
<span class="hljs-keyword">this</span>.pen.x = x;
<span class="hljs-keyword">this</span>.pen.y = y;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
bezierCurveTo(x1, y1, x2, y2, x, y) {
<span class="hljs-keyword">this</span>.path += <span class="hljs-string">'C'</span> +
x1 + <span class="hljs-string">','</span> +
y1 + <span class="hljs-string">','</span> +
x2 + <span class="hljs-string">','</span> +
y2 + <span class="hljs-string">','</span> +
x + <span class="hljs-string">','</span> +
y;
<span class="hljs-keyword">this</span>.pen.x = x;
<span class="hljs-keyword">this</span>.pen.y = y;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
quadraticCurveTo(x1, y1, x, y) {
<span class="hljs-keyword">this</span>.path += <span class="hljs-string">'Q'</span> +
x1 + <span class="hljs-string">','</span> +
y1 + <span class="hljs-string">','</span> +
x + <span class="hljs-string">','</span> +
y;
<span class="hljs-keyword">this</span>.pen.x = x;
<span class="hljs-keyword">this</span>.pen.y = y;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}</pre></div>
<p>This is an attempt (hack) to simulate the HTML5 canvas
arc method.</p>
<div class='highlight'><pre> arc(x, y, radius, startAngle, endAngle, antiClockwise) {
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">normalizeAngle</span>(<span class="hljs-params">angle</span>) </span>{
<span class="hljs-keyword">while</span> (angle < <span class="hljs-number">0</span>) {
angle += <span class="hljs-built_in">Math</span>.PI * <span class="hljs-number">2</span>;
}
<span class="hljs-keyword">while</span> (angle > <span class="hljs-built_in">Math</span>.PI * <span class="hljs-number">2</span>) {
angle -= <span class="hljs-built_in">Math</span>.PI * <span class="hljs-number">2</span>;
}
<span class="hljs-keyword">return</span> angle;
}
startAngle = normalizeAngle(startAngle);
endAngle = normalizeAngle(endAngle);
<span class="hljs-keyword">if</span> (startAngle > endAngle) {
<span class="hljs-keyword">const</span> tmp = startAngle;
startAngle = endAngle;
endAngle = tmp;
antiClockwise = !antiClockwise;
}
<span class="hljs-keyword">const</span> delta = endAngle - startAngle;
<span class="hljs-keyword">if</span> (delta > <span class="hljs-built_in">Math</span>.PI) {
<span class="hljs-keyword">this</span>.arcHelper(x, y, radius, startAngle, startAngle + delta / <span class="hljs-number">2</span>, antiClockwise);
<span class="hljs-keyword">this</span>.arcHelper(x, y, radius, startAngle + delta / <span class="hljs-number">2</span>, endAngle, antiClockwise);
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">this</span>.arcHelper(x, y, radius, startAngle, endAngle, antiClockwise);
}
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
arcHelper(x, y, radius, startAngle, endAngle, antiClockwise) {
<span class="hljs-keyword">const</span> x1 = x + radius * <span class="hljs-built_in">Math</span>.cos(startAngle);
<span class="hljs-keyword">const</span> y1 = y + radius * <span class="hljs-built_in">Math</span>.sin(startAngle);
<span class="hljs-keyword">const</span> x2 = x + radius * <span class="hljs-built_in">Math</span>.cos(endAngle);
<span class="hljs-keyword">const</span> y2 = y + radius * <span class="hljs-built_in">Math</span>.sin(endAngle);
<span class="hljs-keyword">let</span> largeArcFlag = <span class="hljs-number">0</span>;
<span class="hljs-keyword">let</span> sweepFlag = <span class="hljs-number">0</span>;
<span class="hljs-keyword">if</span> (antiClockwise) {
sweepFlag = <span class="hljs-number">1</span>;
<span class="hljs-keyword">if</span> (endAngle - startAngle < <span class="hljs-built_in">Math</span>.PI) {
largeArcFlag = <span class="hljs-number">1</span>;
}
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (endAngle - startAngle > <span class="hljs-built_in">Math</span>.PI) {
largeArcFlag = <span class="hljs-number">1</span>;
}
<span class="hljs-keyword">this</span>.path += <span class="hljs-string">'M'</span> + x1 + <span class="hljs-string">','</span> + y1 + <span class="hljs-string">',A'</span> +
radius + <span class="hljs-string">','</span> + radius + <span class="hljs-string">',0,'</span> + largeArcFlag + <span class="hljs-string">','</span> + sweepFlag + <span class="hljs-string">','</span> +
x2 + <span class="hljs-string">','</span> + y2 + <span class="hljs-string">'M'</span> + <span class="hljs-keyword">this</span>.pen.x + <span class="hljs-string">','</span> + <span class="hljs-keyword">this</span>.pen.y;
}</pre></div>
<p>Adapted from the source for Raphael’s Element.glow</p>
<div class='highlight'><pre> glow() {
<span class="hljs-keyword">const</span> out = <span class="hljs-keyword">this</span>.paper.set();
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.shadow_attributes.width > <span class="hljs-number">0</span>) {
<span class="hljs-keyword">const</span> sa = <span class="hljs-keyword">this</span>.shadow_attributes;
<span class="hljs-keyword">const</span> num_paths = sa.width / <span class="hljs-number">2</span>;
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">1</span>; i <= num_paths; i++) {
out.push(<span class="hljs-keyword">this</span>.paper.path(<span class="hljs-keyword">this</span>.path).attr({
<span class="hljs-attr">stroke</span>: sa.color,
<span class="hljs-string">'stroke-linejoin'</span>: <span class="hljs-string">'round'</span>,
<span class="hljs-string">'stroke-linecap'</span>: <span class="hljs-string">'round'</span>,
<span class="hljs-string">'stroke-width'</span>: +(sa.width / num_paths * i).toFixed(<span class="hljs-number">3</span>),
<span class="hljs-attr">opacity</span>: +((sa.opacity || <span class="hljs-number">0.3</span>) / num_paths).toFixed(<span class="hljs-number">3</span>),</pre></div>
<p>See note in this.scale(): In Raphael the scale() method
is deprecated and removed as of Raphael 2.0 and replaced
by the transform() method. It is preserved here for
users with earlier versions of Raphael, but has no effect
on the output SVG in Raphael 2.0+.</p>
<div class='highlight'><pre> transform: <span class="hljs-keyword">this</span>.attributes.transform,
<span class="hljs-attr">scale</span>: <span class="hljs-keyword">this</span>.attributes.scale,
}));
}
}
<span class="hljs-keyword">return</span> out;
}
fill() {
<span class="hljs-keyword">const</span> elem = <span class="hljs-keyword">this</span>.paper.path(<span class="hljs-keyword">this</span>.path)
.attr(<span class="hljs-keyword">this</span>.attributes)
.attr(<span class="hljs-string">'stroke-width'</span>, <span class="hljs-number">0</span>);
<span class="hljs-keyword">this</span>.glow(elem);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
stroke() {</pre></div>
<p>The first line of code below is, unfortunately, a bit of a hack:
Raphael’s transform() scaling does not scale the stroke-width, so
in order to scale a stroke, we have to manually scale the
stroke-width.</p>
<p>This works well so long as the X & Y states for this.scale() are
relatively similar. However, if they are very different, we
would expect horizontal and vertical lines to have different
stroke-widths.</p>
<p>In the future, if we want to support very divergent values for
horizontal and vertical scaling, we may want to consider
implementing SVG scaling with properties of the SVG viewBox &
viewPort and removing it entirely from the Element.attr() calls.
This would more closely parallel the approach taken in
canvascontext.js as well.</p>
<div class='highlight'><pre>
<span class="hljs-keyword">const</span> strokeWidth = <span class="hljs-keyword">this</span>.lineWidth * (<span class="hljs-keyword">this</span>.state.scale.x + <span class="hljs-keyword">this</span>.state.scale.y) / <span class="hljs-number">2</span>;
<span class="hljs-keyword">const</span> elem = <span class="hljs-keyword">this</span>.paper.path(<span class="hljs-keyword">this</span>.path)
.attr(<span class="hljs-keyword">this</span>.attributes)
.attr(<span class="hljs-string">'fill'</span>, <span class="hljs-string">'none'</span>)
.attr(<span class="hljs-string">'stroke-width'</span>, strokeWidth);
<span class="hljs-keyword">this</span>.glow(elem);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
closePath() {
<span class="hljs-keyword">this</span>.path += <span class="hljs-string">'Z'</span>;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
measureText(text) {
<span class="hljs-keyword">const</span> txt = <span class="hljs-keyword">this</span>.paper.text(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, text)
.attr(<span class="hljs-keyword">this</span>.attributes)
.attr(<span class="hljs-string">'fill'</span>, <span class="hljs-string">'none'</span>)
.attr(<span class="hljs-string">'stroke'</span>, <span class="hljs-string">'none'</span>);
<span class="hljs-keyword">const</span> bounds = txt.getBBox();
txt.remove();
<span class="hljs-keyword">return</span> {
<span class="hljs-attr">width</span>: bounds.width,
<span class="hljs-attr">height</span>: bounds.height,
};
}
fillText(text, x, y) {
<span class="hljs-keyword">this</span>.paper
.text(
x + (<span class="hljs-keyword">this</span>.measureText(text).width / <span class="hljs-number">2</span>),
y - (<span class="hljs-keyword">this</span>.state.font_size / (<span class="hljs-number">2.25</span> * <span class="hljs-keyword">this</span>.state.scale.y)),
text
)
.attr(<span class="hljs-keyword">this</span>.attributes);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
save() {</pre></div>
<p>TODO(mmuthanna): State needs to be deep-copied.</p>
<div class='highlight'><pre> <span class="hljs-keyword">this</span>.state_stack.push({
<span class="hljs-attr">state</span>: {
<span class="hljs-attr">font_family</span>: <span class="hljs-keyword">this</span>.state.font_family,
},
<span class="hljs-attr">attributes</span>: {
<span class="hljs-attr">font</span>: <span class="hljs-keyword">this</span>.attributes.font,
<span class="hljs-attr">fill</span>: <span class="hljs-keyword">this</span>.attributes.fill,
<span class="hljs-attr">stroke</span>: <span class="hljs-keyword">this</span>.attributes.stroke,
<span class="hljs-string">'stroke-width'</span>: <span class="hljs-keyword">this</span>.attributes[<span class="hljs-string">'stroke-width'</span>],
},
<span class="hljs-attr">shadow_attributes</span>: {
<span class="hljs-attr">width</span>: <span class="hljs-keyword">this</span>.shadow_attributes.width,
<span class="hljs-attr">color</span>: <span class="hljs-keyword">this</span>.shadow_attributes.color,
},
});
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
restore() {</pre></div>
<p>TODO(0xfe): State needs to be deep-restored.</p>
<div class='highlight'><pre> <span class="hljs-keyword">const</span> state = <span class="hljs-keyword">this</span>.state_stack.pop();
<span class="hljs-keyword">this</span>.state.font_family = state.state.font_family;
<span class="hljs-keyword">this</span>.attributes.font = state.attributes.font;
<span class="hljs-keyword">this</span>.attributes.fill = state.attributes.fill;
<span class="hljs-keyword">this</span>.attributes.stroke = state.attributes.stroke;
<span class="hljs-keyword">this</span>.attributes[<span class="hljs-string">'stroke-width'</span>] = state.attributes[<span class="hljs-string">'stroke-width'</span>];
<span class="hljs-keyword">this</span>.shadow_attributes.width = state.shadow_attributes.width;
<span class="hljs-keyword">this</span>.shadow_attributes.color = state.shadow_attributes.color;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
}</pre></div>
<div class="fleur">h</div>
</div>
</div>
</body>
</html>