animatry
Version:
Javascript animation library.
127 lines (122 loc) • 5.1 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.splitText = factory());
})(this, (function () { 'use strict';
const select = (input) => {
if (typeof input === 'string') {
const match = input.match(/\w+\[(\d+)\]/);
if (match) {
const index = parseInt(match[1], 10);
const elements = document.querySelectorAll(input.replace(`[${match[1]}]`, ''));
return [elements[index]];
}
return Array.from(document.querySelectorAll(input));
}
else if (input instanceof Element) {
return [input];
}
else if (input instanceof NodeList || input instanceof Array) {
return Array.from(input).flatMap(entry => select(entry));
}
else if (input instanceof Document) {
return [input.documentElement];
}
warn('Could not collect these elements:' + input);
return [];
};
const _p = 'background-color:rgba(0,0,0,0.5);padding:3px 7.5px;';
const warn = (m) => { console.warn(`%cAnimatry%c ${m}`, _p, ''); };
function splitText(elements, options) {
elements = select(elements);
const splitChars = /char/.test(options);
const splitWords = /word/.test(options);
const splitLines = /line/.test(options);
const lines = [];
const words = [];
const chars = [];
elements.forEach((element) => {
element.style.minWidth = element.clientWidth + 'px';
const clone = element.cloneNode(true);
const processNode = (node) => {
var _a;
if (node.nodeType === Node.TEXT_NODE) {
const textContent = (_a = node.textContent) !== null && _a !== void 0 ? _a : '';
if (textContent.trim() === '')
return;
const wordsArray = textContent.split(/(\s+)/);
const container = document.createDocumentFragment();
wordsArray.forEach((wordString) => {
if (wordString.trim() !== '') {
const word = document.createElement('span');
word.classList.add('word');
word.style.display = 'inline-block';
if (splitChars) {
wordString.split('').forEach((charString) => {
const char = document.createElement('span');
char.classList.add('char');
char.style.display = 'inline-block';
char.textContent = charString;
word.appendChild(char);
chars.push(char);
});
}
else {
word.textContent = wordString;
}
container.appendChild(word);
words.push(word);
}
else {
container.appendChild(document.createTextNode(' '));
}
});
node.replaceWith(container);
}
else if (node.nodeType === Node.ELEMENT_NODE) {
Array.from(node.childNodes).forEach(processNode);
}
};
if (splitWords || splitChars || splitLines) {
processNode(clone);
}
const processLines = () => {
const nodes = Array.from(clone.childNodes);
element.innerHTML = '';
const lineFragments = [];
let currentHeight = 0;
function createLine(node) {
const lineFragment = document.createElement('div');
lineFragment.classList.add('line');
lineFragment.appendChild(node);
element.appendChild(lineFragment);
currentHeight = lineFragment.clientHeight;
lineFragments.push(lineFragment);
}
if (nodes.length > 0) {
createLine(nodes.shift());
}
while (nodes.length > 0) {
const lastLine = lineFragments[lineFragments.length - 1];
lastLine.appendChild(nodes.shift());
if (lastLine.clientHeight > currentHeight) {
createLine(lastLine.lastChild);
}
}
return lineFragments;
};
if (splitLines) {
lines.push(...processLines());
}
else {
element.replaceWith(clone);
}
});
return {
lines,
words,
chars,
};
}
return splitText;
}));