Hype TextPath (text on path animation)

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

6 Likes

Nice Max!
Honking%20Horn%20right

Thank you.

Hint: found this if one really needs to go IE9< (http://www.useragentman.com/blog/2013/05/20/cross-browser-svg-text-paths-without-javascript-even-in-older-ie/)

Nice one.
This is the Nuts. I can see it being used a lot when v4 comes out.

+1 very nice!

Would be great if this was part of 4 one day.

1 Like

I did a quick test and it looks like this works with Shape Morphing at the same time too!

1 Like

Sure it does as it uses the original path and it doesn’t break any of the Hype 4 references to the generated content. It also takes the full content from the text (DIV) so you can in theory inject <tspan> tags with dx/dy-attributes or colors. Making this somehow a dedicated tool in Hype would have the benefit of live preview OR you open up the interface for extensions then we can program live previews for extensions we write in the IDE.

1 Like

Absolutely - it was on the list to do, but like a lot of things got pushed off to a later release :). I’m stoked there’s now a way to do this in v4.0.0.

1 Like

So everybody knows what we are talking about.

8 Likes

Great job Max! So many possibilities . . . I can’t wait to use it in a project.

Max I want to throw you a curve ball. See if there’s a way to repurpose what you did and add on top of it to recreate a trail effect type on path just like I have in this motion export? I can provide an apple motion file.

1 Like

Great stuff! Love it!!

You would just need to use some JS to run on the SVG Text element.

https://www.w3schools.com/howto/howto_js_typewriter.asp

2 Likes

Cool, If you notice there was tracking (spacing between the letters) applied in addition to text on path. Anyhow, an example in a form a hype file would be much appreciated.

I move this out the beta forum as the shape tool is now official!

2 Likes

Hi Max

Great work you guys have done here!

Hoping you're still active in this place as i have a question regarding the along-path-animation. I would like to run text along a path with sharp corners. Unfortunately the letters overlap in the corners. Is there a way to avoid this? In your example only the uppercase letters overlap, not the others. See videos attached.

Thank you so much!
Tom


HypeTextPath.hype.zip (31.5 KB)

I always wanted to rewrite this with Hype Data Decorator … :wink:
You can just use dominant-baseline - SVG: Scalable Vector Graphics | MDN

<style>

.customBaseline svg text {
	dominant-baseline: central;
}

</style>

and apply your baseline to the path!

3 Likes

Works great, thank you Max!
:pray: