scrawl-canvas
Version:
Version 8.9.4 - 19 Nov 2022
1,108 lines (737 loc) • 197 kB
HTML
<!DOCTYPE html>
<html>
<head>
<title>Phrase factory</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
<link rel="stylesheet" media="all" href="../../docco.css" />
</head>
<body>
<div id="container">
<div id="background"></div>
<ul id="jump_to">
<li>
<a class="large" href="javascript:void(0);">Jump To …</a>
<a class="small" href="javascript:void(0);">+</a>
<div id="jump_wrapper">
<div id="jump_page_wrapper">
<div id="jump_page">
<a class="source" href="../core/animationloop.html">
./source/core/animationloop.js
</a>
<a class="source" href="../core/document.html">
./source/core/document.js
</a>
<a class="source" href="../core/events.html">
./source/core/events.js
</a>
<a class="source" href="../core/init.html">
./source/core/init.js
</a>
<a class="source" href="../core/library.html">
./source/core/library.js
</a>
<a class="source" href="../core/random-seed.html">
./source/core/random-seed.js
</a>
<a class="source" href="../core/snippets.html">
./source/core/snippets.js
</a>
<a class="source" href="../core/userInteraction.html">
./source/core/userInteraction.js
</a>
<a class="source" href="../core/utilities.html">
./source/core/utilities.js
</a>
<a class="source" href="action.html">
./source/factory/action.js
</a>
<a class="source" href="anchor.html">
./source/factory/anchor.js
</a>
<a class="source" href="animation.html">
./source/factory/animation.js
</a>
<a class="source" href="bezier.html">
./source/factory/bezier.js
</a>
<a class="source" href="block.html">
./source/factory/block.js
</a>
<a class="source" href="canvas.html">
./source/factory/canvas.js
</a>
<a class="source" href="cell.html">
./source/factory/cell.js
</a>
<a class="source" href="cog.html">
./source/factory/cog.js
</a>
<a class="source" href="color.html">
./source/factory/color.js
</a>
<a class="source" href="conicGradient.html">
./source/factory/conicGradient.js
</a>
<a class="source" href="coordinate.html">
./source/factory/coordinate.js
</a>
<a class="source" href="crescent.html">
./source/factory/crescent.js
</a>
<a class="source" href="element.html">
./source/factory/element.js
</a>
<a class="source" href="emitter.html">
./source/factory/emitter.js
</a>
<a class="source" href="filter.html">
./source/factory/filter.js
</a>
<a class="source" href="filterEngine-bluenoiseData.html">
./source/factory/filterEngine-bluenoiseData.js
</a>
<a class="source" href="filterEngine.html">
./source/factory/filterEngine.js
</a>
<a class="source" href="fontAttributes.html">
./source/factory/fontAttributes.js
</a>
<a class="source" href="gradient.html">
./source/factory/gradient.js
</a>
<a class="source" href="grid.html">
./source/factory/grid.js
</a>
<a class="source" href="group.html">
./source/factory/group.js
</a>
<a class="source" href="imageAsset.html">
./source/factory/imageAsset.js
</a>
<a class="source" href="line.html">
./source/factory/line.js
</a>
<a class="source" href="lineSpiral.html">
./source/factory/lineSpiral.js
</a>
<a class="source" href="loom.html">
./source/factory/loom.js
</a>
<a class="source" href="mesh.html">
./source/factory/mesh.js
</a>
<a class="source" href="net.html">
./source/factory/net.js
</a>
<a class="source" href="noiseAsset.html">
./source/factory/noiseAsset.js
</a>
<a class="source" href="oval.html">
./source/factory/oval.js
</a>
<a class="source" href="palette.html">
./source/factory/palette.js
</a>
<a class="source" href="particle.html">
./source/factory/particle.js
</a>
<a class="source" href="particleForce.html">
./source/factory/particleForce.js
</a>
<a class="source" href="particleHistory.html">
./source/factory/particleHistory.js
</a>
<a class="source" href="particleSpring.html">
./source/factory/particleSpring.js
</a>
<a class="source" href="particleWorld.html">
./source/factory/particleWorld.js
</a>
<a class="source" href="pattern.html">
./source/factory/pattern.js
</a>
<a class="source" href="phrase.html">
./source/factory/phrase.js
</a>
<a class="source" href="picture.html">
./source/factory/picture.js
</a>
<a class="source" href="polygon.html">
./source/factory/polygon.js
</a>
<a class="source" href="polyline.html">
./source/factory/polyline.js
</a>
<a class="source" href="quadratic.html">
./source/factory/quadratic.js
</a>
<a class="source" href="quaternion.html">
./source/factory/quaternion.js
</a>
<a class="source" href="radialGradient.html">
./source/factory/radialGradient.js
</a>
<a class="source" href="rawAsset.html">
./source/factory/rawAsset.js
</a>
<a class="source" href="rdAsset.html">
./source/factory/rdAsset.js
</a>
<a class="source" href="rectangle.html">
./source/factory/rectangle.js
</a>
<a class="source" href="renderAnimation.html">
./source/factory/renderAnimation.js
</a>
<a class="source" href="shape.html">
./source/factory/shape.js
</a>
<a class="source" href="spiral.html">
./source/factory/spiral.js
</a>
<a class="source" href="spriteAsset.html">
./source/factory/spriteAsset.js
</a>
<a class="source" href="stack.html">
./source/factory/stack.js
</a>
<a class="source" href="star.html">
./source/factory/star.js
</a>
<a class="source" href="state.html">
./source/factory/state.js
</a>
<a class="source" href="tetragon.html">
./source/factory/tetragon.js
</a>
<a class="source" href="ticker.html">
./source/factory/ticker.js
</a>
<a class="source" href="tracer.html">
./source/factory/tracer.js
</a>
<a class="source" href="tween.html">
./source/factory/tween.js
</a>
<a class="source" href="unstackedElement.html">
./source/factory/unstackedElement.js
</a>
<a class="source" href="vector.html">
./source/factory/vector.js
</a>
<a class="source" href="videoAsset.html">
./source/factory/videoAsset.js
</a>
<a class="source" href="wheel.html">
./source/factory/wheel.js
</a>
<a class="source" href="../mixin/anchor.html">
./source/mixin/anchor.js
</a>
<a class="source" href="../mixin/asset.html">
./source/mixin/asset.js
</a>
<a class="source" href="../mixin/assetAdvancedFunctionality.html">
./source/mixin/assetAdvancedFunctionality.js
</a>
<a class="source" href="../mixin/assetConsumer.html">
./source/mixin/assetConsumer.js
</a>
<a class="source" href="../mixin/base.html">
./source/mixin/base.js
</a>
<a class="source" href="../mixin/cascade.html">
./source/mixin/cascade.js
</a>
<a class="source" href="../mixin/delta.html">
./source/mixin/delta.js
</a>
<a class="source" href="../mixin/displayShape.html">
./source/mixin/displayShape.js
</a>
<a class="source" href="../mixin/dom.html">
./source/mixin/dom.js
</a>
<a class="source" href="../mixin/entity.html">
./source/mixin/entity.js
</a>
<a class="source" href="../mixin/filter.html">
./source/mixin/filter.js
</a>
<a class="source" href="../mixin/mimic.html">
./source/mixin/mimic.js
</a>
<a class="source" href="../mixin/path.html">
./source/mixin/path.js
</a>
<a class="source" href="../mixin/pattern.html">
./source/mixin/pattern.js
</a>
<a class="source" href="../mixin/pivot.html">
./source/mixin/pivot.js
</a>
<a class="source" href="../mixin/position.html">
./source/mixin/position.js
</a>
<a class="source" href="../mixin/shapeBasic.html">
./source/mixin/shapeBasic.js
</a>
<a class="source" href="../mixin/shapeCurve.html">
./source/mixin/shapeCurve.js
</a>
<a class="source" href="../mixin/shapePathCalculation.html">
./source/mixin/shapePathCalculation.js
</a>
<a class="source" href="../mixin/styles.html">
./source/mixin/styles.js
</a>
<a class="source" href="../mixin/tween.html">
./source/mixin/tween.js
</a>
</div>
</div>
</li>
</ul>
<ul class="sections">
<li id="section-1">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-1">§</a>
</div>
<h1 id="phrase-factory">Phrase factory</h1>
<p>Phrase entitys are graphical text rectangles rendered onto a DOM <canvas> element using the Canvas API’s <a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D">CanvasRenderingContext2D interface</a> - in particular the <code>fillRect</code>, <code>strokeRect</code>, <code>fillText</code> and <code>strokeText</code> methods.</p>
<ul>
<li>Positioning functionality for the Phrase is supplied by the <strong>position</strong> mixin, while rendering functionality comes from the <strong>entity</strong> mixin. </li>
<li>Phrases can use CSS color Strings for their fillStyle and strokeStyle values, alongside <strong>Gradient</strong>, <strong>RadialGradient</strong>, <strong>Color</strong> and <strong>Pattern</strong> objects. </li>
<li>They will also accept <strong>Filter</strong> objects.</li>
<li>They can use <strong>Anchor</strong> objects for user navigation. </li>
<li>They can be rendered to the canvas by including them in a <strong>Cell</strong> object’s <strong>Group</strong>. </li>
<li>They can be <strong>animated</strong> directly, or using delta animation, or act as the target for <strong>Tween</strong> animations.</li>
<li>Phrases can be cloned, and killed.</li>
</ul>
<p>Phrase entity <strong>dimensions</strong> work differently to that of other entitys:</p>
<ul>
<li>The <code>width</code> attribute is required for multi-line text. When set, Phrase entitys will automatically render text longer than its width in multiple lines on the canvas.</li>
<li>The <code>height</code> attribute is normally disregarded. Instead height is calculated as a combination of the font <code>size</code>, <code>lineheight</code>, and the number of lines of text that need to be rendered on the canvas - which itself depends on the text’s length and the entity’s <code>width</code> attribute.</li>
</ul>
<p><strong>Be aware that text is <em>always</em> rendered as a graphic, not a block.</strong> </p>
<ul>
<li>Scrawl-canvas ignores all attempts to set the canvas context engine’s <code>textAlign</code> and <code>textBaseline</code> attributes, which are permanently set to the defaults <code>left</code> and <code>top</code> respectively. </li>
<li>Each glyph (letter) is stamped separately onto the canvas - this allows us to include letterspacing and justification functionality, and to allow text to be styled on a per-glyph basis (overline/underline, highlight, color, bold/italics, etc).</li>
</ul>
<p>Phrase entitys use <a href="./fontAttribute.html">FontAttribute objects</a> to help manage their text font:</p>
<ul>
<li>More than one font family can be used in a single Phrase.</li>
<li>Font styles are also supported: a single Phrase can include multiple episodes of <strong>bold</strong>, <em>italic</em>, etc.</li>
<li>More than one font size can be displayed within a Phrase.</li>
<li>Letter spacing is supported, both across the entire text and within the text.</li>
<li>Beyond fonts, ranges of letters within the Phrase text can be background highlighted, or given overlines and/or underlines.</li>
</ul>
<p>Phrase entitys fully support <strong>text along a path</strong> at the Phrase, word and letter levels.</p>
<p>Phrase entity text content is <strong>accessible to assistive technologies</strong> such as screen readers, by default.</p>
</div>
</li>
<li id="section-2">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-2">§</a>
</div>
<h4 id="demos">Demos:</h4>
<ul>
<li><a href="../../demo/canvas-015.html">Canvas-015</a> - Phrase entity (make, clone, method, multiline)</li>
<li><a href="../../demo/canvas-016.html">Canvas-016</a> - Phrase entity position and font attributes; Block mimic functionality</li>
<li><a href="../../demo/canvas-017.html">Canvas-017</a> - Phrase entity - test lineHeight, letterSpacing and justify attributes; setSectionStyles() functionality</li>
<li><a href="../../demo/canvas-018.html">Canvas-018</a> - Phrase entity - text along a path</li>
<li><a href="../../demo/canvas-029.html">Canvas-029</a> - Phrase entitys and gradients</li>
<li><a href="../../demo/snippets-001.html">Snippets-001</a> - Scrawl-canvas DOM element snippets</li>
<li><a href="../../demo/packets-002.html">Packets-002</a> - Scrawl-canvas packets - save and load a range of different entitys</li>
<li><a href="../../demo/modules-001.html">Modules-001</a> - Scrawl-canvas modularized code - London crime charts</li>
</ul>
</div>
</li>
<li id="section-3">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-3">§</a>
</div>
<h4 id="todo">TODO:</h4>
<p>The <a href="https://developer.mozilla.org/en-US/docs/Web/API/CSS_Font_Loading_API">CSS Font Loading API</a> is beginning to stabilize across browsers, which means we can watch for font loads and then perform text measurements using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics">TextMetrics interface</a></p>
<ul>
<li>Currently we need to calculate font/text height using temporary DOM elements - this is both ugly and less than accurate</li>
<li>Text metrics will give us much better height measurements, and also glyph width measurements (and thus advance values for eg text along a path)</li>
<li>However progress with the enhanced TextMetrics is slower across browsers, meaning that any code we develop is likely to bloat the code base as we cannot (yet) afford to discard existing code.</li>
<li>More details in Demo <a href="../../demo/canvas-029.html">Canvas-029</a> - Phrase entitys and gradients</li>
</ul>
</div>
</li>
<li id="section-4">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-4">§</a>
</div>
<h4 id="imports">Imports</h4>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">import</span> { constructors, cell, cellnames, styles, stylesnames, artefact, sectionClasses } <span class="hljs-keyword">from</span> <span class="hljs-string">'../core/library.js'</span>;
<span class="hljs-keyword">import</span> { scrawlCanvasHold } <span class="hljs-keyword">from</span> <span class="hljs-string">'../core/document.js'</span>;
<span class="hljs-keyword">import</span> { mergeOver, pushUnique, xt, xta, isa_obj, isa_number, Ωempty } <span class="hljs-keyword">from</span> <span class="hljs-string">'../core/utilities.js'</span>;
<span class="hljs-keyword">import</span> { requestCell, releaseCell } <span class="hljs-keyword">from</span> <span class="hljs-string">'./cell.js'</span>;
<span class="hljs-keyword">import</span> { makeFontAttributes } <span class="hljs-keyword">from</span> <span class="hljs-string">'./fontAttributes.js'</span>;
<span class="hljs-keyword">import</span> baseMix <span class="hljs-keyword">from</span> <span class="hljs-string">'../mixin/base.js'</span>;
<span class="hljs-keyword">import</span> entityMix <span class="hljs-keyword">from</span> <span class="hljs-string">'../mixin/entity.js'</span>;</pre></div></div>
</li>
<li id="section-5">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-5">§</a>
</div>
<p>Constants used by Phrase entitys</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">const</span> defaultTextForHeightMeasurements = <span class="hljs-string">'|/}ÁÅþ§¶¿∑ƒ⌈⌊qwertyd0123456789QWERTY'</span>;
<span class="hljs-keyword">const</span> fontHeightCalculator = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">createElement</span>(<span class="hljs-string">'div'</span>);
fontHeightCalculator.<span class="hljs-property">style</span>.<span class="hljs-property">padding</span> = <span class="hljs-number">0</span>;
fontHeightCalculator.<span class="hljs-property">style</span>.<span class="hljs-property">border</span> = <span class="hljs-number">0</span>;
fontHeightCalculator.<span class="hljs-property">style</span>.<span class="hljs-property">margin</span> = <span class="hljs-number">0</span>;
fontHeightCalculator.<span class="hljs-property">style</span>.<span class="hljs-property">height</span> = <span class="hljs-string">'auto'</span>;
fontHeightCalculator.<span class="hljs-property">style</span>.<span class="hljs-property">lineHeight</span> = <span class="hljs-number">1</span>;
fontHeightCalculator.<span class="hljs-property">style</span>.<span class="hljs-property">boxSizing</span> = <span class="hljs-string">'border-box'</span>;
fontHeightCalculator.<span class="hljs-property">innerHTML</span> = defaultTextForHeightMeasurements;
fontHeightCalculator.<span class="hljs-title function_">setAttribute</span>(<span class="hljs-string">'aria-hidden'</span>, <span class="hljs-string">'true'</span>);
scrawlCanvasHold.<span class="hljs-title function_">appendChild</span>(fontHeightCalculator);
<span class="hljs-keyword">const</span> textEntityConverter = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">createElement</span>(<span class="hljs-string">'textarea'</span>);</pre></div></div>
</li>
<li id="section-6">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-6">§</a>
</div>
<p><strong>ensureFloat</strong> - return the value provided as a floating point number of given precision; return 0 if not a number</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">const</span> <span class="hljs-title function_">ensureFloat</span> = (<span class="hljs-params">val, precision</span>) => {
val = <span class="hljs-built_in">parseFloat</span>(val);
<span class="hljs-keyword">if</span> (!<span class="hljs-title function_">isa_number</span>(val)) val = <span class="hljs-number">0</span>;
<span class="hljs-keyword">if</span> (!<span class="hljs-title function_">isa_number</span>(precision)) precision = <span class="hljs-number">0</span>;
<span class="hljs-keyword">return</span> <span class="hljs-built_in">parseFloat</span>(val.<span class="hljs-title function_">toFixed</span>(precision));
};</pre></div></div>
</li>
<li id="section-7">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-7">§</a>
</div>
<p><strong>ensurePositiveFloat</strong> - return the value provided as a positive floating point number of given precision; return 0 if not a number</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">const</span> <span class="hljs-title function_">ensurePositiveFloat</span> = (<span class="hljs-params">val, precision</span>) => {
val = <span class="hljs-built_in">parseFloat</span>(val);
<span class="hljs-keyword">if</span> (!<span class="hljs-title function_">isa_number</span>(val)) val = <span class="hljs-number">0</span>;
<span class="hljs-keyword">if</span> (!<span class="hljs-title function_">isa_number</span>(precision)) precision = <span class="hljs-number">0</span>;
<span class="hljs-keyword">return</span> <span class="hljs-title class_">Math</span>.<span class="hljs-title function_">abs</span>(<span class="hljs-built_in">parseFloat</span>(val.<span class="hljs-title function_">toFixed</span>(precision)));
};</pre></div></div>
</li>
<li id="section-8">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-8">§</a>
</div>
<p><strong>ensureString</strong> - return a String representation of the value</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">const</span> <span class="hljs-title function_">ensureString</span> = (<span class="hljs-params">val</span>) => {
<span class="hljs-keyword">return</span> (val.<span class="hljs-property">substring</span>) ? val : val.<span class="hljs-property">toString</span>;
};</pre></div></div>
</li>
<li id="section-9">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-9">§</a>
</div>
<h4 id="phrase-constructor">Phrase constructor</h4>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">const</span> <span class="hljs-title class_">Phrase</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params">items = Ωempty</span>) {
<span class="hljs-variable language_">this</span>.<span class="hljs-property">fontAttributes</span> = <span class="hljs-title function_">makeFontAttributes</span>(Ωempty);
<span class="hljs-variable language_">this</span>.<span class="hljs-title function_">entityInit</span>(items);
<span class="hljs-variable language_">this</span>.<span class="hljs-property">dirtyDimensions</span> = <span class="hljs-literal">true</span>;
<span class="hljs-variable language_">this</span>.<span class="hljs-property">dirtyText</span> = <span class="hljs-literal">true</span>;
<span class="hljs-variable language_">this</span>.<span class="hljs-property">dirtyFont</span> = <span class="hljs-literal">true</span>;
<span class="hljs-variable language_">this</span>.<span class="hljs-property">dirtyPathObject</span> = <span class="hljs-literal">true</span>;
<span class="hljs-keyword">return</span> <span class="hljs-variable language_">this</span>;
};</pre></div></div>
</li>
<li id="section-10">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-10">§</a>
</div>
<h4 id="phrase-prototype">Phrase prototype</h4>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">let</span> P = <span class="hljs-title class_">Phrase</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span> = <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">create</span>(<span class="hljs-title class_">Object</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>);
P.<span class="hljs-property">type</span> = <span class="hljs-string">'Phrase'</span>;
P.<span class="hljs-property">lib</span> = <span class="hljs-string">'entity'</span>;
P.<span class="hljs-property">isArtefact</span> = <span class="hljs-literal">true</span>;
P.<span class="hljs-property">isAsset</span> = <span class="hljs-literal">false</span>;</pre></div></div>
</li>
<li id="section-11">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-11">§</a>
</div>
<h4 id="mixins">Mixins</h4>
<ul>
<li><a href="../mixin/base.html">base</a></li>
<li><a href="../mixin/entity.html">entity</a></li>
</ul>
</div>
<div class="content"><div class='highlight'><pre>P = <span class="hljs-title function_">baseMix</span>(P);
P = <span class="hljs-title function_">entityMix</span>(P);
P.<span class="hljs-property">midInitActions</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params">items</span>) {
<span class="hljs-variable language_">this</span>.<span class="hljs-property">sectionStyles</span> = [];</pre></div></div>
</li>
<li id="section-12">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-12">§</a>
</div>
<p>this.sectionClasses = {
‘DEFAULTS’: { defaults: true },
‘BOLD’: { weight: ‘bold’ },
‘ITALIC’: { style: ‘italic’ },
‘SMALL-CAPS’: { variant: ‘small-caps’ },
‘HIGHLIGHT’: { highlight: true },
‘UNDERLINE’: { underline: true },
‘OVERLINE’: { overline: true },
‘/BOLD’: { weight: ‘normal’ },
‘/ITALIC’: { style: ‘normal’ },
‘/SMALL-CAPS’: { variant: ‘normal’ },
‘/HIGHLIGHT’: { highlight: false },
‘/UNDERLINE’: { underline: false },
‘/OVERLINE’: { overline: false }
};</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-variable language_">this</span>.<span class="hljs-property">sectionClasses</span> = sectionClasses;
};</pre></div></div>
</li>
<li id="section-13">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-13">§</a>
</div>
<h4 id="phrase-attributes">Phrase attributes</h4>
<ul>
<li>Attributes defined in the <a href="../mixin/base.html">base mixin</a>: <strong>name</strong>.</li>
<li>Attributes defined in the <a href="../mixin/position.html">position mixin</a>: <strong>group, visibility, order, calculateOrder, stampOrder, start, <em>startX</em>, <em>startY</em>, handle, <em>handleX</em>, <em>handleY</em>, offset, <em>offsetX</em>, <em>offsetY</em>, dimensions, <em>width</em>, <em>height</em>, pivoted, mimicked, lockTo, <em>lockXTo</em>, <em>lockYTo</em>, scale, roll, noUserInteraction, noPositionDependencies, noCanvasEngineUpdates, noFilters, noPathUpdates, purge, bringToFrontOnDrag</strong>.</li>
<li>Attributes defined in the <a href="../mixin/delta.html">delta mixin</a>: <strong>delta, noDeltaUpdates</strong>.</li>
<li>Attributes defined in the <a href="../mixin/pivot.html">pivot mixin</a>: <strong>pivot, pivotCorner, addPivotHandle, addPivotOffset, addPivotRotation</strong>.</li>
<li>Attributes defined in the <a href="../mixin/mimic.html">mimic mixin</a>: <strong>mimic, useMimicDimensions, useMimicScale, useMimicStart, useMimicHandle, useMimicOffset, useMimicRotation, useMimicFlip, addOwnDimensionsToMimic, addOwnScaleToMimic, addOwnStartToMimic, addOwnHandleToMimic, addOwnOffsetToMimic, addOwnRotationToMimic</strong>.</li>
<li>Attributes defined in the <a href="../mixin/path.html">path mixin</a>: <strong>path, pathPosition, addPathHandle, addPathOffset, addPathRotation, constantPathSpeed</strong>.</li>
<li>Attributes defined in the <a href="../mixin/entity.html">entity mixin</a>: <strong>method, pathObject, winding, flipReverse, flipUpend, scaleOutline, lockFillStyleToEntity, lockStrokeStyleToEntity, onEnter, onLeave, onDown, onUp, <em>fillStyle, strokeStyle, globalAlpha, globalCompositeOperation, lineWidth, lineCap, lineJoin, lineDash, lineDashOffset, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, filter</em></strong>.</li>
<li>Attributes defined in the <a href="../mixin/anchor.html">anchor mixin</a>: <strong>anchor</strong>.</li>
<li>Attributes defined in the <a href="../mixin/filter.html">filter mixin</a>: <strong>filters, isStencil</strong>.</li>
</ul>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">let</span> defaultAttributes = {</pre></div></div>
</li>
<li id="section-14">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-14">§</a>
</div>
<p><strong>text</strong> - the text String to be displayed by the Phrase</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-attr">text</span>: <span class="hljs-string">''</span>,</pre></div></div>
</li>
<li id="section-15">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-15">§</a>
</div>
<p><strong>width</strong> - Number or String</p>
<ul>
<li>In addition to normal dimensional values, Phrase entitys will accept the String label <strong>‘auto’</strong> (default). When set to ‘auto’ the width will be calculated as the natural, single line text length.</li>
</ul>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-attr">width</span>: <span class="hljs-string">'auto'</span>,</pre></div></div>
</li>
<li id="section-16">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-16">§</a>
</div>
<p><strong>exposeText</strong> - Boolean accessibility feature</p>
<ul>
<li>When <strong>exposeText</strong> is set to true (default), Scrawl-canvas will create an element in the DOM and mirror its current text value in that element. </li>
<li>The element - a <div> - is attached to the canvas element’s textHold element, which immediately follows that element and has zero dimensions, so its contents don’t interfere with the flow of the rest of the DOM content.</li>
</ul>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-attr">exposeText</span>: <span class="hljs-literal">true</span>,</pre></div></div>
</li>
<li id="section-17">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-17">§</a>
</div>
<p><strong>lineHeight</strong> - a positive float Number multiplier applied to the font height to add space between lines of text</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-attr">lineHeight</span>: <span class="hljs-number">1.15</span>,</pre></div></div>
</li>
<li id="section-18">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-18">§</a>
</div>
<p><strong>letterSpacing</strong> - a positive float Number representing a set number of pixels to place between each glyph (letter). Can be overridden for letter ranges using styling objects</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-attr">letterSpacing</span>: <span class="hljs-number">0</span>,</pre></div></div>
</li>
<li id="section-19">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-19">§</a>
</div>
<p><strong>justify</strong> - String value to indicate how the text should justify itself within its dimensions box.</p>
<ul>
<li>Permitted values are: <code>left</code> (default), <code>center</code>, <code>right</code>, <code>full</code> (for ‘justified’ text).</li>
</ul>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-attr">justify</span>: <span class="hljs-string">'left'</span>,</pre></div></div>
</li>
<li id="section-20">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-20">§</a>
</div>
<h5 id="in-text-styling">In-text styling</h5>
</div>
</li>
<li id="section-21">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-21">§</a>
</div>
<p><strong>sectionClasses</strong> - Array of styling objects</p>
<p>Glyphs (letters) can be individually styled by adding a <em><strong>styling object</strong></em> to the <code>sectionClasses</code> Array, and then adding <strong>section style markup</strong> to the Phrase’s text String attribute. Subsequent glyphs will inherit those styles until a second style marker updating or terminating that particular style is encountered.</p>
<p>The following font attributes can be modified on a per-glyph basis using section classes:</p>
<ul>
<li><code>style</code> - eg ‘italic’</li>
<li><code>variant</code> - eg ‘small-caps’</li>
<li><code>weight</code> - eg ‘bold’</li>
<li><code>stretch</code></li>
<li><code>size</code> - any permitted font size value</li>
<li><code>family</code> - font family</li>
<li><code>space</code> - alter the letterSpacing values to spread or condense glyphs</li>
<li><code>fill</code> - fillStyle to be applied to the glyph</li>
<li><code>stroke</code> - strokeStyle to be applied to the glyph</li>
<li><code>highlight</code> - boolean - whether highlight should be applied to the glyph</li>
<li><code>underline</code> - boolean - whether underline should be applied to the glyph</li>
<li><code>overline</code> - boolean - whether overline should be applied to the glyph</li>
<li><code>defaults</code> - boolean - setting this to true will set the glyph (and subsequent glyphs) to the Phrase entity’s current font and fill/stroke style values</li>
</ul>
<p>Usage: </p>
<ol>
<li>Add styling objects to the <code>sectionClasses</code> Array - a number of styling objects are pre-defined for every Phrase entity; these can be added to, modified or deleted at any time using the <code>addSectionClass</code> and <code>removeSectionClass</code> functions.</li>
<li>If necessary, update the entity’s <code>sectionClassMarker</code> delimiter attrbute. The attribute has to be a String, but that string can define a Regular Expression - for example setting the attribute to <code>[§<>]</code> will identify style markup delimeted by both <code>§marker-label§</code> and <code><marker-label></code>.</li>
<li>Add section style markup to the Phrase entity’s text attribute value.</li>
</ol>
<pre><code><span class="hljs-keyword">let</span> myPhrase = scrawl.<span class="hljs-title function_">makePhrase</span>({
<span class="hljs-attr">name</span>: <span class="hljs-string">'my-phrase'</span>,
<span class="hljs-attr">text</span>: <span class="hljs-string">'This is §RED§some red text§DEFAULTS§ for demonstration.'</span>
});
myPhrase.<span class="hljs-title function_">addSectionClass</span>(<span class="hljs-string">'RED'</span>, { <span class="hljs-attr">fill</span>: <span class="hljs-string">'red'</span> });
</code></pre>
<p>The following classes are pre-defined for every Phrase entity:</p>
<ul>
<li><code>DEFAULTS</code> - remove all inline glyph styling from this point on</li>
<li><code>BOLD</code>, <code>/BOLD</code> - add/remove bold styling</li>
<li><code>ITALIC</code>, <code>/ITALIC</code> - add/remove italic styling</li>
<li><code>SMALL-CAPS</code>, <code>/SMALL-CAPS</code> - add/remove small-caps styling</li>
<li><code>HIGHLIGHT</code>, <code>/HIGHLIGHT</code> - add/remove glyph background highlight</li>
<li><code>UNDERLINE</code>, <code>/UNDERLINE</code> - add/remove glyph underline</li>
<li><code>OVERLINE</code>, <code>/OVERLINE</code> - add/remove glyph overline</li>
</ul>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-attr">sectionClassMarker</span>: <span class="hljs-string">'[§<>]'</span>,
<span class="hljs-attr">sectionClasses</span>: <span class="hljs-literal">null</span>,</pre></div></div>
</li>
<li id="section-22">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-22">§</a>
</div>
<h5 id="overlines-underlines-highlighting">Overlines, underlines, highlighting</h5>
<p>We set the position and style for overlines, underlines and background highlight on a per-Phrase entity level, then apply them to glyphs using <strong>sectionClasses</strong> styling objects.</p>
<ul>
<li>over/underline decoration positions are float Numbers (generally) in the range <code>0 - 1</code> which represent where on the Phrase text line the decoration should appear. The values are relative to line heights, which in turn depend on font size and Phrase lineHeight attributes.</li>
<li>for <strong>strikethrough</strong> text, use appropriately positioned overlines.</li>
<li>over/underline decoration style values, and the highlight style value, can be any valid CSS color String.</li>
</ul>
</div>
</li>
<li id="section-23">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-23">§</a>
</div>
<p><strong>overlinePosition</strong>, <strong>overlineStyle</strong></p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-attr">overlinePosition</span>: -<span class="hljs-number">0.1</span>,
<span class="hljs-attr">overlineStyle</span>: <span class="hljs-string">'rgb(250,0,0)'</span>,
<span class="hljs-attr">overlineWidth</span>: <span class="hljs-number">1</span>,
<span class="hljs-attr">noOverlineGlyphs</span>: <span class="hljs-string">''</span>,</pre></div></div>
</li>
<li id="section-24">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-24">§</a>
</div>
<p><strong>underlinePosition</strong>, <strong>underlineStyle</strong></p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-attr">underlinePosition</span>: <span class="hljs-number">0.6</span>,
<span class="hljs-attr">underlineStyle</span>: <span class="hljs-string">'rgb(250,0,0)'</span>,
<span class="hljs-attr">underlineWidth</span>: <span class="hljs-number">1</span>,
<span class="hljs-attr">noUnderlineGlyphs</span>: <span class="hljs-string">''</span>,</pre></div></div>
</li>
<li id="section-25">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-25">§</a>
</div>
<p><strong>highlightStyle</strong></p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-attr">highlightStyle</span>: <span class="hljs-string">'rgba(250,218,94,0.4)'</span>,</pre></div></div>
</li>
<li id="section-26">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-26">§</a>
</div>
<h5 id="bounding-box">Bounding box</h5>
<p>The bounding box represents the Phrase entity’s collision detection <em><strong>hit area</strong></em>. It contains all of the entity’s text, including line spacing.</p>
</div>
</li>
<li id="section-27">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-27">§</a>
</div>
<p><strong>boundingBoxColor</strong></p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-attr">boundingBoxColor</span>: <span class="hljs-string">'rgba(0,0,0,0.5)'</span>,</pre></div></div>
</li>
<li id="section-28">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-28">§</a>
</div>
<p><strong>showBoundingBox</strong> - Boolean flag indicating whether the Phrase entity’s bounding box should be displayed</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-attr">showBoundingBox</span>: <span class="hljs-literal">false</span>,</pre></div></div>
</li>
<li id="section-29">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-29">§</a>
</div>
<h5 id="text-along-a-path">Text along a path</h5>
<p>Phrase entitys, alongside other artefacts, can use a <a href="./shape.html">Shape entity</a> as a <em><strong>reference path</strong></em> to determine its location in the canvas display - achieved by setting the <code>path</code>, <code>pathPosition</code>, etc attributes as required.</p>
<ul>
<li>In this case, the Phrase’s text will appear as boxed text, with straight lines of text.</li>
</ul>
<p>We have an ad