Объединение двух матричных преобразований в одном преобразовании с 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 без полифилла