Объединение двух матричных преобразований в одном преобразовании с SVG

Моя текущая задача - попытаться объединить объекты с одинаковыми матрицами под одной матрицей преобразования. Две матрицы всегда будут иметь первые 4 цифры своего преобразования равными. У меня проблемы с вычислением x="???" и у = "???" для второго tspan. Любая помощь в правильном уравнении будет принята с благодарностью.

вход

<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>

Выход

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

РЕДАКТИРОВАТЬ 1

Я предполагаю, что мой вопрос больше похож на заданную точку (x,y), как мне применить существующее матричное преобразование к этой точке, чтобы позиция не двигалась, но элемент теперь будет вложен в другой элемент.

РЕДАКТИРОВАТЬ 2

Я получил этот код для работы с матрицами с 0 в позициях (a, d) или (b,c). Наклонные / перекошенные матрицы у меня еще не заработали. Есть мысли по этому поводу?

        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 ответ

Решение

Одна мысль, которая может сработать, если моя логика не ошибочна, - это найти преобразование для одного элемента в другой, который затем можно использовать для преобразования точки 0,0 (так как это исходные x,y) в новую место нахождения.

Как только мы узнаем, в чем заключается различие в преобразованиях (если предположить, что первые 4 цифры в матрице совпадают с указанными в вопросе, иначе это не сработает), мы сможем выяснить, в чем заключается различие в x, y.

Во-первых, немного кода, так как некоторые браузеры удалили эту функцию.

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

Это метод svg, который поддерживается некоторыми браузерами, но в том числе и как полифилл, если ваш не поддерживает (например, Chrome). Он находит преобразование из одного элемента в другой.

Затем мы можем использовать это, чтобы найти преобразование от первого до второго текстового элемента.

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

var transform = text2.getTransformToElement( text1 )

Или, если вы не хотите, чтобы polyfill, это может работать (матрицы не моя сильная сторона!). getCTM() получает текущую матрицу преобразования элемента.

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

Теперь мы знаем, что было преобразованием между ними. Мы также знаем, что оригинал х, у был 0,0. Таким образом, мы можем создать точку svg 0,0 и затем преобразовать ее с помощью матрицы, которую мы только что вычислили, чтобы найти новые x, y.

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

Тогда просто отложенный пример, чтобы показать, что он перемещается. Установите tspan с новым x, y, который мы только что выяснили из предыдущего преобразования.

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

jsfiddle с полифиллом

jsfiddle без полифилла

Другие вопросы по тегам