933d61de19
* added ESLint and updated all code base * updated SVGPathCommander, CubicBezier, shorter-js, minifill * updated polyfills * minor CSS fixes
179 lines
5.6 KiB
JavaScript
179 lines
5.6 KiB
JavaScript
import connect from '../objects/connect.js';
|
|
import numbers from '../interpolation/numbers.js';
|
|
|
|
import { onStartWrite, charSet } from './textWriteBase.js';
|
|
|
|
// Component Util
|
|
// utility for multi-child targets
|
|
// wrapContentsSpan returns an [Element] with the SPAN.tagName and a desired class
|
|
function wrapContentsSpan(el, classNAME) {
|
|
let textWriteWrapper;
|
|
let newElem;
|
|
if (typeof (el) === 'string') {
|
|
newElem = document.createElement('SPAN');
|
|
newElem.innerHTML = el;
|
|
newElem.className = classNAME;
|
|
return newElem;
|
|
}
|
|
if (!el.children.length || (el.children.length && el.children[0].className !== classNAME)) {
|
|
const elementInnerHTML = el.innerHTML;
|
|
textWriteWrapper = document.createElement('SPAN');
|
|
textWriteWrapper.className = classNAME;
|
|
textWriteWrapper.innerHTML = elementInnerHTML;
|
|
el.appendChild(textWriteWrapper);
|
|
el.innerHTML = textWriteWrapper.outerHTML;
|
|
} else if (el.children.length && el.children[0].className === classNAME) {
|
|
[textWriteWrapper] = el.children;
|
|
}
|
|
return textWriteWrapper;
|
|
}
|
|
|
|
function getTextPartsArray(el, classNAME) {
|
|
let elementsArray = [];
|
|
const len = el.children.length;
|
|
if (len) {
|
|
const textParts = [];
|
|
let remainingMarkup = el.innerHTML;
|
|
let wrapperParts;
|
|
|
|
for (let i = 0, currentChild, childOuter, unTaggedContent; i < len; i += 1) {
|
|
currentChild = el.children[i];
|
|
childOuter = currentChild.outerHTML;
|
|
wrapperParts = remainingMarkup.split(childOuter);
|
|
|
|
if (wrapperParts[0] !== '') {
|
|
unTaggedContent = wrapContentsSpan(wrapperParts[0], classNAME);
|
|
textParts.push(unTaggedContent);
|
|
remainingMarkup = remainingMarkup.replace(wrapperParts[0], '');
|
|
} else if (wrapperParts[1] !== '') {
|
|
unTaggedContent = wrapContentsSpan(wrapperParts[1].split('<')[0], classNAME);
|
|
textParts.push(unTaggedContent);
|
|
remainingMarkup = remainingMarkup.replace(wrapperParts[0].split('<')[0], '');
|
|
}
|
|
|
|
if (!currentChild.classList.contains(classNAME)) currentChild.classList.add(classNAME);
|
|
textParts.push(currentChild);
|
|
remainingMarkup = remainingMarkup.replace(childOuter, '');
|
|
}
|
|
|
|
if (remainingMarkup !== '') {
|
|
const unTaggedRemaining = wrapContentsSpan(remainingMarkup, classNAME);
|
|
textParts.push(unTaggedRemaining);
|
|
}
|
|
|
|
elementsArray = elementsArray.concat(textParts);
|
|
} else {
|
|
elementsArray = elementsArray.concat([wrapContentsSpan(el, classNAME)]);
|
|
}
|
|
return elementsArray;
|
|
}
|
|
|
|
function setSegments(target, newText) {
|
|
const oldTargetSegs = getTextPartsArray(target, 'text-part');
|
|
const newTargetSegs = getTextPartsArray(wrapContentsSpan(newText), 'text-part');
|
|
|
|
target.innerHTML = '';
|
|
target.innerHTML += oldTargetSegs.map((s) => { s.className += ' oldText'; return s.outerHTML; }).join('');
|
|
target.innerHTML += newTargetSegs.map((s) => { s.className += ' newText'; return s.outerHTML.replace(s.innerHTML, ''); }).join('');
|
|
|
|
return [oldTargetSegs, newTargetSegs];
|
|
}
|
|
|
|
export function createTextTweens(target, newText, ops) {
|
|
if (target.playing) return false;
|
|
|
|
const options = ops || {};
|
|
options.duration = 1000;
|
|
|
|
if (ops.duration === 'auto') {
|
|
options.duration = 'auto';
|
|
} else if (Number.isFinite(ops.duration * 1)) {
|
|
options.duration = ops.duration * 1;
|
|
}
|
|
|
|
const TweenContructor = connect.tween;
|
|
const segs = setSegments(target, newText);
|
|
const oldTargetSegs = segs[0];
|
|
const newTargetSegs = segs[1];
|
|
const oldTargets = [].slice.call(target.getElementsByClassName('oldText')).reverse();
|
|
const newTargets = [].slice.call(target.getElementsByClassName('newText'));
|
|
|
|
let textTween = [];
|
|
let totalDelay = 0;
|
|
|
|
textTween = textTween.concat(oldTargets.map((el, i) => {
|
|
options.duration = options.duration === 'auto'
|
|
? oldTargetSegs[i].innerHTML.length * 75
|
|
: options.duration;
|
|
options.delay = totalDelay;
|
|
options.onComplete = null;
|
|
|
|
totalDelay += options.duration;
|
|
return new TweenContructor(el, { text: el.innerHTML }, { text: '' }, options);
|
|
}));
|
|
textTween = textTween.concat(newTargets.map((el, i) => {
|
|
function onComplete() {
|
|
target.innerHTML = newText;
|
|
target.playing = false;
|
|
}
|
|
|
|
options.duration = options.duration === 'auto' ? newTargetSegs[i].innerHTML.length * 75 : options.duration;
|
|
options.delay = totalDelay;
|
|
options.onComplete = i === newTargetSegs.length - 1 ? onComplete : null;
|
|
totalDelay += options.duration;
|
|
|
|
return new TweenContructor(el, { text: '' }, { text: newTargetSegs[i].innerHTML }, options);
|
|
}));
|
|
|
|
textTween.start = function startTweens() {
|
|
if (!target.playing) {
|
|
textTween.forEach((tw) => tw.start());
|
|
target.playing = true;
|
|
}
|
|
};
|
|
|
|
return textTween;
|
|
}
|
|
|
|
// Component Functions
|
|
function getWrite(/* tweenProp, value */) {
|
|
return this.element.innerHTML;
|
|
}
|
|
|
|
function prepareText(tweenProp, value) {
|
|
if (tweenProp === 'number') {
|
|
return parseFloat(value);
|
|
}
|
|
// empty strings crash the update function
|
|
return value === '' ? ' ' : value;
|
|
}
|
|
|
|
// All Component Functions
|
|
export const textWriteFunctions = {
|
|
prepareStart: getWrite,
|
|
prepareProperty: prepareText,
|
|
onStart: onStartWrite,
|
|
};
|
|
|
|
/* textWrite = {
|
|
category: 'textWrite',
|
|
defaultValues: {},
|
|
interpolators: {numbers},
|
|
functions = { prepareStart, prepareProperty, onStart }
|
|
} */
|
|
|
|
// Full Component
|
|
export const textWrite = {
|
|
component: 'textWriteProperties',
|
|
category: 'textWrite',
|
|
properties: ['text', 'number'],
|
|
defaultValues: { text: ' ', numbers: '0' },
|
|
defaultOptions: { textChars: 'alpha' },
|
|
Interpolate: { numbers },
|
|
functions: textWriteFunctions,
|
|
// export to global for faster execution
|
|
Util: { charSet, createTextTweens },
|
|
};
|
|
|
|
export default textWrite;
|