How to bake the transform matrix into path coordinates with Raphael JS 2
Right click the T and hit "Inspect Element" to see the actual path data.
by Chris Ball
HTML
<svg xmlns="http://www.w3.org/2000/svg" viewBox="291 197 45 39">
<path id="black" transform="matrix(0.1389, 0, 0, 0.1389, 291.91, 235.465)" d="M150,-265C182,-275,171,-220,180,-194L178,-194C181,-192,180,-185,181,-180C211,-169,282,-173,306,-166C308,-169,316,-171,315,-165C268,-157,225,-148,184,-137C188,-118,186,-96,190,-79L282,-131C289,-131,296,-135,297,-126C293,-118,271,-105,236,-80C190,-48,155,-20,125,-6C112,-15,115,-34,111,-51C121,-70,108,-107,107,-133C70,-132,-5,-126,0,-157C18,-170,39,-181,64,-191C75,-190,92,-181,100,-185C99,-198,95,-211,89,-225Z">
</svg>
CSS
body { background: #445; }
#pink {
stroke-width: 0.1;
stroke: pink;
fill: rgba(255,0,0,0.1);
}
JavaScript
// Helper tool to piece together Raphael's paths into strings again
Array.prototype.flatten || (Array.prototype.flatten = function() {
return this.reduce(function(a, b) {
return a.concat('function' === typeof b.flatten ? b.flatten() : b);
}, []);
});
// The only reason to create a new element here is to show that it's perfectly
// overlaid with the original – you can just as well be destructive on `path`:
var path = document.querySelector('path'),
pink = path.parentNode.appendChild(path.cloneNode(false));
pink.id = 'pink';
pink.setAttribute('d', applyTransforms(pink));
pink.removeAttribute('transform');
// done!
// Uses Raphael.path2curve and Raphael.pathToRelative
//
// Calculates a new <path d> attribute relative to a given root (<svg>) element,
// folding in all the transforms into the path data itself so it can move there,
// and get rid of its transform attribute.
function applyTransforms(path, root) {
function point(x, y) { var p = svg.createSVGPoint(); p.x=x; p.y=y; return p; }
// add a copy of the path at the same level of the hierarchy to see transforms
path = path.parentElement.appendChild(path.cloneNode(false));
// turn all arc commands into splines so we can transform them even with skews
path.setAttribute('d', path2curve(path));
var svg = path.ownerSVGElement
, normal = (root||svg).getCTM().inverse() // compensation for root's scaling
, matrix = normal.multiply(path.getCTM()) // transform, relative to svg root
, _ = ''
, coords = [_, 1, 2] // main and optional handle 1 and 2 coordinates
, segs = path.pathSegList
, len = segs.numberOfItems
, x = { 0: 0, '': 0, 1: 0, 2: 0 }
, y = { 0: 0, '': 0, 1: 0, 2: 0 }
, i = -1
, seg, cmd
;
// simplify the logic by normalizing to absolute coordinates first
absolutizePath(path);
// walk the path, applying all transforms between us and the root as we go
while (++i < len) {
seg = segs.getItem(i);
cmd =...