Hype TextPath (Beta)
Animated demo here
So as we now have path information in Hype we can manipulate… how about using that for a nice text path animation. Assign a class that starts with textPath to your vector path and assign the same class to your text with the addition content. So for example assign to your first path the class textPathOne and to the corresponding text the class textPathOne content. Use the line animation to move the text along the line. That’s it.
Put this code snippet in your Head HTML …
<script>
function HypeTextPath(hypeDocument, element, event) {
/* get scene */
var sceneElm = document.querySelector('#'+hypeDocument.documentId()+' > .HYPE_scene[style*="block"]');
/* helper for offset transfer from stroke dashoffset to textpath offset */
var setStartOffset = function(path, textPath){
if (typeof path.getAttribute('stroke-dasharray') === 'string') {
var p = Number(path.getAttribute('stroke-dashoffset'));
var l = path.getTotalLength();
textPath.setAttribute('startOffset', ((1-p/l)*100).toFixed(2)+'%');
}
}
/* fetch selector for textPath svg */
var nElmAll = sceneElm.querySelectorAll ('div[class*="textPath"] svg');
/* process them */
nElmAll.forEach (function(nElm) {
var textPathID = nElm.parentNode.classList[1];
if (textPathID.length>8) {
var tElm = sceneElm.querySelector('.'+textPathID+'.content');
var pElm = nElm.querySelector ('path');
/* hide path */
pElm.style.opacity = 0;
pElm.style.pointerEvents = 'none';
/* hide text */
tElm.style.opacity= 0;
/* add text to path */
var nsSvg = "http://www.w3.org/2000/svg";
var nsXlink = 'http://www.w3.org/1999/xlink'
var svgtElm = document.createElementNS(nsSvg, "text");
var svgtpElm = document.createElementNS(nsSvg, "textPath");
svgtElm.appendChild(svgtpElm);
/* copy content */
svgtpElm.innerHTML = tElm.innerHTML;
/* transfer and translate styles frm HTML to SVG */
var keys = ['fontFamily','fontSize',['color','fill'], 'letterSpacing', 'wordSpacing'];
for (var i=0; i<keys.length; i++) {
var isArray = typeof keys[i] === 'object';
var hKey = isArray ? keys[i][0] : keys[i];
var vKey = isArray ? keys[i][1] : keys[i];
svgtElm.style[vKey] = tElm.style[hKey];
}
/* fix overflow based on font size */
var buffer =parseInt(svgtElm.style.fontSize);
nElm.style.setProperty('padding', buffer+'px', 'important');
nElm.style.setProperty('margin-left', '-'+buffer+'px', 'important');
nElm.style.setProperty('margin-top', '-'+buffer+'px', 'important');
nElm.style.setProperty ('overflow', 'visible', 'important');
/* link path*/
svgtpElm.setAttributeNS(nsXlink, 'xlink:href', '#'+pElm.id);
svgtpElm.setAttribute( 'href', '#'+pElm.id);
/* set initial offset */
setStartOffset (pElm,svgtpElm);
/* append to SVG */
nElm.appendChild(svgtElm);
/* listen to and act on changes */
var mutationObserver = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.attributeName == 'stroke-dashoffset') {
setStartOffset (mutation.target,svgtpElm);
}
});
});
mutationObserver.observe(pElm, {
attributes: true
});
}
});
return true;
}
if("HYPE_eventListeners" in window === false) {
window.HYPE_eventListeners = Array();
}
window.HYPE_eventListeners.push({"type":"HypeSceneLoad", "callback":HypeTextPath});
</script>
Example Download:
HypeTextPath.hype.zip
Versionhistory:
1.0 Initial release under MIT-license




