Skip to content

Commit

Permalink
Merge pull request #105 from peterhry/split-hook
Browse files Browse the repository at this point in the history
Support a custom splitter function
  • Loading branch information
peterhry authored May 27, 2018
2 parents cae2937 + 2b8f2ee commit 4b981c7
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 173 deletions.
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ A CircleType instance creates a circular text element.
**Kind**: global class

* [CircleType](#CircleType)
* [new CircleType(elem)](#new_CircleType_new)
* [new CircleType(elem, [splitter])](#new_CircleType_new)
* [.radius(value)](#CircleType+radius)[<code>CircleType</code>](#CircleType)
* [.radius()](#CircleType+radius) ⇒ <code>number</code>
* [.dir(value)](#CircleType+dir)[<code>CircleType</code>](#CircleType)
Expand All @@ -48,11 +48,12 @@ A CircleType instance creates a circular text element.

<a name="new_CircleType_new"></a>

### new CircleType(elem)
### new CircleType(elem, [splitter])

| Param | Type | Description |
| --- | --- | --- |
| elem | <code>HTMLElement</code> | A target HTML element. |
| [splitter] | <code>function</code> | An optional function used to split the element's text content into individual characters |

**Example**
```js
Expand All @@ -61,6 +62,14 @@ const circleType = new CircleType(document.getElementById('myElement'));

// Set the text radius and direction. Note: setter methods are chainable.
circleType.radius(200).dir(-1);

// Provide your own splitter function to handle emojis
// @see https://github.com/orling/grapheme-splitter
const splitter = new GraphemeSplitter()
new CircleType(
document.getElementById('myElement'),
splitter.splitGraphemes.bind(splitter)
);
```
<a name="CircleType+radius"></a>

Expand Down
8 changes: 2 additions & 6 deletions assets/stylesheets/screen.css
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,9 @@ h3 {

code {
display: block;
background: #101010;
color: #fff;
font-family: "Andale Mono", AndaleMono, monospace;
font-size: 12px;
padding: 1em;
font-size: 14px;
padding: 1em !important;
margin: 0 0 4em;
white-space: pre;
}

footer {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions dist/circletype.min.js

Large diffs are not rendered by default.

172 changes: 40 additions & 132 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
<script src="https://use.typekit.net/fbl0lhq.js"></script>
<link rel="shortcut icon" type="image/x-icon" href="assets/favicon.ico">
<link rel="stylesheet" href="assets/stylesheets/screen.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/monokai-sublime.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
</head>
<body>
<div class="container">
Expand All @@ -31,175 +33,75 @@ <h2 class="strong">Features</h2>
<a href="https://github.com/peterhry/circletype" class="btn">Download on GitHub</a>
</p>

<ins
class="adsbygoogle"
style="display:block"
data-ad-format="fluid"
data-ad-layout="text-only"
data-ad-layout-key="-gw-c+2p-30-2w"
data-ad-client="ca-pub-2609593449239823"
data-ad-slot="9041076570">
</ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<h2 class="strong">Demos</h2>
<h3 class="puffy">Basic Arc</h3>
<p>Here’s some curved text that flows clockwise.</p>
<div class="demo-box" id="demo-box1">
<h2 id="demo1" class="demo strong">Here’s some curved text flowing clockwise.</h2>
</div>
<code>&lt;h2 id="demo1"&gt;Here’s some curved text flowing clockwise.&lt;/h2&gt;
new CircleType(document.getElementById('demo1')).radius(384);</code>

<ins
class="adsbygoogle"
style="display:block"
data-ad-format="fluid"
data-ad-layout="text-only"
data-ad-layout-key="-gw-c+2p-30-2w"
data-ad-client="ca-pub-2609593449239823"
data-ad-slot="9041076570">
</ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<pre><code class="javascript">// &lt;h2 id="demo1">Here’s some curved text flowing clockwise.&lt;/h2&gt;
new CircleType(document.getElementById('demo1'))
.radius(384);</code></pre>
<h3 class="puffy" id="reverse">Reversed Arc</h3>
<p>By setting dir to -1, the text will flow counter-clockwise instead.</p>
<div class="demo-box" id="demo-box2">
<h2 id="demo2" class="demo strong">Here’s some curved text flowing counter-clockwise.</h2>
</div>
<code>&lt;h2 id="demo2"&gt;Here’s some curved text flowing counter-clockwise.&lt;/h2&gt;
new CircleType(document.getElementById('demo2')).dir(-1).radius(384);</code>

<ins
class="adsbygoogle"
style="display:block"
data-ad-format="fluid"
data-ad-layout="text-only"
data-ad-layout-key="-gw-c+2p-30-2w"
data-ad-client="ca-pub-2609593449239823"
data-ad-slot="9041076570">
</ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<pre><code class="js">// &lt;h2 id="demo2">Here’s some curved text flowing counter-clockwise.&lt;/h2&gt;
new CircleType(document.getElementById('demo2'))
.dir(-1)
.radius(384);</code></pre>
<h3 class="puffy" id="auto">Auto Radius</h3>
<p>By leaving the radius empty, CircleType.js will find the perfect radius so the text makes a complete rotation.</p>
<div class="demo-box" id="demo-box3">
<h2 id="demo3" class="demo strong">This text makes a complete rotation no matter how long it is. </h2>
</div>
<code>&lt;h2 id="demo3"&gt;This text makes a complete rotation no matter how long it is. &lt;/h2&gt;
new CircleType(document.getElementById('demo3'));</code>

<ins
class="adsbygoogle"
style="display:block"
data-ad-format="fluid"
data-ad-layout="text-only"
data-ad-layout-key="-gw-c+2p-30-2w"
data-ad-client="ca-pub-2609593449239823"
data-ad-slot="9041076570">
</ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<pre><code class="js">// &lt;h2 id="demo3">This text makes a complete rotation no matter how long it is. &lt;/h2&gt;
new CircleType(document.getElementById('demo3'));</code></pre>
<h3 class="puffy" id="fluid">Fluid</h3>
<p>Update the radius when the window is resized to create a fluid effect (try resizing your window).</p>
<div class="demo-box" id="demo-box4">
<h2 id="demo4" class="demo strong">This curved type shrinks and expands to fit inside its container. </h2>
</div>
<code>&lt;h2 id="demo4"&gt;This curved type shrinks and expands to fit inside its container. &lt;/h2&gt;
<pre><code class="js">// &lt;h2 id="demo4">This curved type shrinks and expands to fit inside its container. &lt;/h2&gt;
var demo4 = new CircleType(document.getElementById('demo4'));
window.addEventListener('resize', function updateRadius() {
demo4.radius(demo4.element.offsetWidth / 2);
});
updateRadius();</code>

<ins
class="adsbygoogle"
style="display:block"
data-ad-format="fluid"
data-ad-layout="text-only"
data-ad-layout-key="-gw-c+2p-30-2w"
data-ad-client="ca-pub-2609593449239823"
data-ad-slot="9041076570">
</ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

updateRadius();</code></pre>
<h3 class="puffy" id="fitText">Using FitText.js</h3>
<p>Here’s how you can use <a href="http://fittextjs.com" target="_blank">FitText.js</a> to make the text scale (try resizing your window)</p>
<p>Here’s how you can use <a href="http://fittextjs.com" target="_blank">FitText.js</a> to make the text scale (try resizing your window).</p>
<div class="demo-box" id="demo-box5">
<h2 id="demo5" class="demo strong">I play well with FitText.js too! </h2>
</div>
<code>&lt;h2 id="demo5"&gt;I play well with FitText.js too! &lt;/h2&gt;
var demo5 = new CircleType(document.getElementById('demo5')).radius(180);
$(demo5.element).fitText();</code>

<ins
class="adsbygoogle"
style="display:block"
data-ad-format="fluid"
data-ad-layout="text-only"
data-ad-layout-key="-gw-c+2p-30-2w"
data-ad-client="ca-pub-2609593449239823"
data-ad-slot="9041076570">
</ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<pre><code class="js">// &lt;h2 id="demo5">I play well with FitText.js too! &lt;/h2&gt;
var demo5 = new CircleType(document.getElementById('demo5'))
.radius(180);
$(demo5.element).fitText();</code></pre>
<h3 class="puffy" id="fitText">Destroy</h3>
<p>Here’s how you can remove the effect from an element.</p>
<div class="demo-box" id="demo-box6">
<p><a href="#" class="btn" id="destroyButton">Destroy Me</a></p>
<h2 id="demo6" class="demo strong">Easily remove the effect.</h2>
</div>
<code>&lt;button id="destroyButton">Destroy Me&lt;/button&gt;
&lt;h2 id="demo6"&gt;Easily remove the effect.&lt;/h2&gt;
var demo6 = new CircleType(document.getElementById('demo6')).radius(180);
document.getElementById('destroyButton').addEventListener('click', demo6.destroy.bind(demo6));</code>

<ins
class="adsbygoogle"
style="display:block"
data-ad-format="fluid"
data-ad-layout="text-only"
data-ad-layout-key="-gw-c+2p-30-2w"
data-ad-client="ca-pub-2609593449239823"
data-ad-slot="9041076570">
</ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<pre><code class="js">// &lt;button id="destroyButton"&gt;Destroy Me&lt;/button&gt;
// &lt;h2 id="demo6"&gt;Easily remove the effect.&lt;/h2&gt;
var demo6 = new CircleType(document.getElementById('demo6'))
.radius(180);
document.getElementById('destroyButton')
.addEventListener('click', demo6.destroy.bind(demo6));</code></pre>
<h3 class="puffy" id="emoji">Emojis</h3>
<p>I work with emojis!</p>
<p>I work with emojis but you’ll need to provide your own splitter function. Here is an example that uses GraphemeSplitter:</p>
<div class="demo-box" id="demo-box7">
<h2 id="demo7" class="demo strong">🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩</h2>
<h2 id="demo7" class="demo strong">👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦</h2>
</div>
<code>&lt;h2 id="demo7"&gt;🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩&lt;/h2&gt;
var demo7 = new CircleType(document.getElementById('demo7'));</code>

<ins
class="adsbygoogle"
style="display:block"
data-ad-format="fluid"
data-ad-layout="text-only"
data-ad-layout-key="-gw-c+2p-30-2w"
data-ad-client="ca-pub-2609593449239823"
data-ad-slot="9041076570">
</ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<pre><code class="js">// &lt;script src="https://cdn.rawgit.com/orling/grapheme-splitter/b4500feb/index.js"&gt;&lt;/script&gt;
// &lt;h2 id="demo7"&gt;👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦👨‍👩‍👧‍👦&lt;/h2&gt;
var splitter = new GraphemeSplitter()
var demo7 = new CircleType(
document.getElementById('demo7'),
splitter.splitGraphemes.bind(splitter)
);</code></pre>
<h2 class="strong">Browser Support</h2>
<ul class="bullets">
<li>Chrome, Firefox, Safari, Opera, Edge (last 2 versions)</li>
Expand All @@ -213,6 +115,7 @@ <h2 class="strong">Browser Support</h2>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FitText.js/1.2.0/jquery.fittext.min.js"></script>
<script src="https://cdn.rawgit.com/orling/grapheme-splitter/b4500feb/index.js"></script>
<script src="dist/circletype.min.js"></script>
<script>
try {
Expand Down Expand Up @@ -280,7 +183,11 @@ <h2 class="strong">Browser Support</h2>
/**
* Emojis
*/
var demo7 = new CircleType(document.getElementById('demo7'));
var splitter = new GraphemeSplitter()
var demo7 = new CircleType(
document.getElementById('demo7'),
splitter.splitGraphemes.bind(splitter)
);
}
</script>
<script type="text/javascript">
Expand All @@ -297,5 +204,6 @@ <h2 class="strong">Browser Support</h2>
<script
async
src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "circletype",
"version": "2.2.1",
"version": "2.3.0",
"description": "A JavaScript library that lets you curve type on the web.",
"main": "dist/circletype.min.js",
"files": [
Expand Down
19 changes: 16 additions & 3 deletions src/class.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,39 @@ const { PI, max, min } = Math;
* A CircleType instance creates a circular text element.
*
* @param {HTMLElement} elem A target HTML element.
* @param {Function} [splitter] An optional function used to split the element's
* text content into individual characters
*
* @example
* // Instantiate `CircleType` with an HTML element.
* const circleType = new CircleType(document.getElementById('myElement'));
*
* // Set the text radius and direction. Note: setter methods are chainable.
* circleType.radius(200).dir(-1);
*
* // Provide your own splitter function to handle emojis
* // @see https://github.com/orling/grapheme-splitter
* const splitter = new GraphemeSplitter()
* new CircleType(
* document.getElementById('myElement'),
* splitter.splitGraphemes.bind(splitter)
* );
*
*/
class CircleType {
constructor(elem) {
constructor(elem, splitter) {
this.element = elem;
this.originalHTML = this.element.innerHTML;

const container = document.createElement('div');
const fragment = document.createDocumentFragment();
container.setAttribute('aria-label', elem.innerText);
container.style.position = 'relative';
this.container = container;

this._letters = splitNode(elem);
this._letters.forEach(letter => container.appendChild(letter));
this._letters = splitNode(elem, splitter);
this._letters.forEach(letter => fragment.appendChild(letter));
container.appendChild(fragment);

this.element.innerHTML = '';
this.element.appendChild(container);
Expand Down
27 changes: 6 additions & 21 deletions src/utils/__tests__/splitNode-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,6 @@ describe('splitNode', () => {
});
});

it('handles any node', () => {
const testText = 'Some test text.';
const { length } = testText;
const nodeTypes = [ 'div', 'a', 'time', 'asdf' ];
const nodes = nodeTypes.map(type => createNode(testText, type));

nodes.forEach(node => expect(splitNode(node)).toHaveLength(length));
});

it('handles nodes with no text content', () => {
expect(splitNode(createNode(''))).toHaveLength(0);
});
Expand All @@ -62,18 +53,12 @@ describe('splitNode', () => {
expect(splitNode(createNode(' '))).toHaveLength(0);
});

it('allows chars to be wrapped by any tag', () => {
const testText = 'X';
const node = createNode(testText);
const [ anchor ] = splitNode(node, 'a');
const [ div ] = splitNode(node, 'div');
const [ button ] = splitNode(node, 'button');
const [ unknown ] = splitNode(node, 'asdf');

expect(anchor).toBeInstanceOf(HTMLAnchorElement);
expect(div).toBeInstanceOf(HTMLDivElement);
expect(button).toBeInstanceOf(HTMLButtonElement);
expect(unknown).toBeInstanceOf(HTMLUnknownElement);
it('accepts a custom splitter function', () => {
const spans = splitNode(
createNode('one-two-three-four'),
string => string.split('-'),
);
expect(spans).toHaveLength(4);
});

it('handles all emojis (chars whose length might be `2`)', () => {
Expand Down
Loading

0 comments on commit 4b981c7

Please sign in to comment.