0
votes

My current task is attempting to combine objects with similar matrices under the same transformation matrix. The two matrices will always have the first 4 digits of it's transform be equal. I am having difficulty calculating the x="???" and y="???" for the second tspan. Any help towards the proper equation would be greatly appreciated.

Input

<svg>
<text transform="matrix(0 1 1 0 100 100)"><tspan x=0 y=0>foo</tspan></text>
<text transform="matrix(0 1 1 0 110 110)"><tspan x=0 y=0>bar</tspan></text>
</svg>

Output

<svg>
<text transform="matrix(0 1 1 0 100 100)">
<tspan x="0" y="0">foo</tspan>
<tspan x="???" y="???">bar</tspan>
</text>
</svg>

EDIT 1

I guess my question is more along the lines of given a point (x,y), how do I apply an existing matrix transformation to that point so that the position will not move, but the element will now be nested inside of another element.

EDIT 2

I have got this code to work for matrices with 0s in the (a,d) or (b,c) positions. Slanted/Skewed matrices I still have not got working. Any thoughts on this?

        var aX = floatX[0];
        var bX = floatX[1];
        var cX = floatX[2];
        var dX = floatX[3];
        var eX = floatX[4];
        var fX = floatX[5];

        var aY = floatY[0];
        var bY = floatY[1];
        var cY = floatY[2];
        var dY = floatY[3];
        var eY = floatY[4];
        var fY = floatY[5];

        var xX = (eX * aX) + (fX * bX);
        var xY = (eX * cX) + (fX * dX);

        var yX = (eY * aY) + (fY * bY);
        var yY = (eY * cY) + (fY * dY);

        var c1 = cX - aX;
        var c2 = dX + bX;

        return new float[] { (yX - xX) / (c1 * c2), (yY - xY) / (c1 * c2) };
1
Isn't it just 10 10 ? Subtract the respective number in the new text transform from the original. - Ian
That's what I initially tried, but if the numbers are different e.g. (0 -0.12 -0.12 0) or (1.2 0 0 -1.2) it doesn't work. - Jacob Scheib
Probably best to update the question with the example which doesn't work then :). - Ian
if the numbers are not (1 0 0 1) or (0 1 1 0) standard matrices, the method mentioned above does not work. I think this may be a lot more complex than I first thought. For example, if the two matrices first 4 digits are (0 -.12 -.12 0) what do you do. - Jacob Scheib
I disagree with you. There are 2 degrees of freedom in both end states, as the first 4 digits of each matrix combination are the same - Jacob Scheib

1 Answers

0
votes

One thought that may work if my logic isn't flawed, is to find the transform for one element to the other, which can then be used to transform a point of 0,0 (as that's the original x,y) to a new location.

Once we know what the difference in transforms is (assuming that the first 4 figures in the matrix are the same as mentioned in the question, it won't work otherwise), we can figure what the difference in x,y is.

First, there's a bit of code as some browsers have removed this feature..

SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformToElement || function(elem) {
    return elem.getScreenCTM().inverse().multiply(this.getScreenCTM());
};

This is an svg method that some browsers support, but including as a polyfill in case yours doesn't (like Chrome). It finds the transform from one element to another.

We can then use this, to find the transform from the first to the second text element.

var text1 = document.querySelector('#myText1')
var text2 = document.querySelector('#myText2')

var transform = text2.getTransformToElement( text1 )

Or if you don't want the polyfill, this 'may' work (matrices aren't a strong point of mine!). getCTM() gets the current transformation matrix of an element.

var transform = text1.getCTM().inverse().multiply( text2.getCTM() )

Now we know what the transform between them was. We also know the original x,y was 0,0. So we can create an svg point 0,0 and then transform it with that matrix we've just figured, to find the new x,y.

var pt = document.querySelector('svg').createSVGPoint();
pt.x = 0; pt.y = 0;
var npt = pt.matrixTransform( transform );

Then just a delayed example to show it being moved. Set the tspan with the new x,y we've just figured from the previous transform.

setTimeout( function() {
    alert('new x,y is ' + npt.x + ',' + npt.y)
    tspan2.setAttribute('x', npt.x);
    tspan2.setAttribute('y', npt.y);
},2000);

jsfiddle with polyfill

jsfiddle without polyfill