Skip to content

Instantly share code, notes, and snippets.

@friendzis
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save friendzis/9362577 to your computer and use it in GitHub Desktop.
Save friendzis/9362577 to your computer and use it in GitHub Desktop.
Modified textOnPath to center text on path and rotate letter based on path direction
// Based on http://stackoverflow.com/a/19122486/478725
// Text is rotated to be read begin -> end
// Variable width fonts will still be a bit off center
var angle = function(v1, v2) {
ang = Math.atan2(v2.y - v1.y, v2.x - v1.x);
return {
radians: ang,
degrees: ang * 180 / Math.PI
};
};
function textOnPath( paper, message, path, fontSize, letterSpacing, kerning, geckoKerning) {
// if fontSize or letterSpacing are undefined, they are calculated to fill the path
// 10% of fontSize is usually good for manual letterspacing
// Gecko, i.e. Firefox etc, inflates and alters the letter spacing
var gecko = /rv:([^\)]+)\) Gecko\/\d{8}/.test(navigator.userAgent||'') ? true : false;
var letters = [], places = [], messageLength = 0;
for (var c=0; c < message.length; c++) {
var letter = paper.text(0, 0, message[c]).attr({"text-anchor" : "middle"});
var character = letter.attr('text'), kern = 0;
letters.push(letter);
if (kerning) {
if(gecko && geckoKerning) {
kerning = geckoKerning;
}
var predecessor = letters[c-1] ? letters[c-1].attr('text') : '';
if (kerning[c]) {
kern = kerning[c];
} else if (kerning[character]) {
if( typeof kerning[character] === 'object' ) {
kern = kerning[character][predecessor] || kerning[character]['default'] || 0;
} else {
kern = kerning[character];
}
}
if(kerning['default'] ) {
kern = kern + (kerning['default'][predecessor] || 0);
}
}
messageLength = messageLength ? messageLength : letter.getBBox().width;
messageLength += kern;
places.push(messageLength);
//spaces get a width of 0, so set min at 4px
messageLength += Math.max(4.5, letter.getBBox().width);
}
if( letterSpacing ){
if (gecko) {
letterSpacing = letterSpacing * 0.83;
}
} else {
letterSpacing = letterSpacing || path.getTotalLength() / messageLength;
}
fontSize = fontSize || 10 * letterSpacing;
for (c = 0; c < letters.length; c++) {
letters[c].attr("font-size", fontSize + "px");
p = path.getPointAtLength(places[c] * letterSpacing);
//var rotate = 'R' + (p.alpha <= 180 ? p.alpha + 180 : p.alpha > 360 ? p.alpha - 360 : p.alpha )+','+p.x+','+p.y;
var pp1 = path.getPointAtLength(places[c]*letterSpacing-0.1),
pp2 = path.getPointAtLength(places[c]*letterSpacing+0.1),
rotate = 'R' + angle(pp1, pp2).degrees +','+p.x+','+p.y;
letters[c].attr({ x: p.x, y: p.y, transform: rotate });
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment