|a c e| |b d g| |0 0 1|Третья строка матрицы для двумерных преобразований всегда одна и та же: 0 0 1. Поэтому ее не учитывают при задании преобразования посредством атрибута вида transform="matrix(a,b,c,d,e,g)" (только 6, а не 9 параметров).
translate (перемещение на x и y px) — matrix(1,0,0,1,x,y) rotate (поворот на угол a) — matrix(cos(a),sin(a),-sin(a),cos(a),0,0) scale (масштабирование с коэффициентами kx и ky) — matrix(kx,0,0,ky,0,0) skewX (наклон вдоль X на угол a) — matrix(1,0,tg(a),1,0,0) skewY (наклон вдоль Y на угол a) — matrix(1,tg(a),0,1,0,0) тождественное преобразование, которое ничего не изменяет — matrix(1,0,0,1,0,0)
Сложное преобразование получается как последовательность элементарных преобразований. Оно описывается матрицей, являющейся результатом произведения матриц, соответствующих элементарным преобразованиям. Матричная запись преобразований компактна, но с трудом поддается интуиции или семантической интерпретации. Вместе с тем, многие типичные преобразования можно понять, выполнив экспериментально произведение нескольких элементарных преобразований подряд и заметив, как формируется результирующая матрица относительно исходной. Так например, легко заметить, что:
function pmatrix(a1,b1,c1,d1,e1,g1,a2,b2,c2,d2,e2,g2){
/* Параметры: значения параметров 1-го и 2-го преобразований
Возвращает строку вида "matrix(a,b,c,d,e,g)",
являющуюся результатом произведения двух матриц
*/
return "matrix("+(a1*a2+c1*b2)+","+
(b1*a2+d1*b2)+","+
(a1*c2+c1*d2)+","+
(b1*c2+d1*d2)+","+
(a1*e2+c1*g2+e1)+","+
(b1*e2+d1*g2+g1)+")"
}
function pmatrix2(s1,s2){
/*Параметры: строки вида "matrix(a,b,c,d,e,g)"
Возвращает строку вида "matrix(a,b,c,d,e,g)",
являющуюся результатом произведения двух матриц
*/
var sep;// разделитель ,бывают "," и пробел
if (s1.indexOf(",")==-1) {sep=' '} else {sep="," };
var l=s1.length
var s1=s1.substring(7,s1.length-1); // содержимое скобок
s1=s1.split(","); // делаем массив
var s2=s2.substring(7,s2.length-1); // содержимое скобок
if (s2.indexOf(",")==-1) {sep=" "} else {sep=","};
s2=s2.split(","); // делаем массив
return "matrix("+(s1[0]*s2[0]+s1[2]*s2[1])+","+
(s1[1]*s2[0]+s1[3]*s2[1])+","+
(s1[0]*s2[2]+s1[2]*s2[3])+","+
(s1[1]*s2[2]+s1[3]*s2[3])+","+
(s1[0]*s2[4]+s1[2]*s2[5]+s1[4]*1)+","+
(s1[1]*s2[4]+s1[3]*s2[5]+s1[5]*1)+")";
}
Далее в примерах я буду использовать функцию pmatrix2(), как наиболее удобную для работы в SVG, когда необходимо с помощью скрипта изменять текущее положение объекта.
Обратите внимание на возню с разделителем в коде этой функции.
Дело в том, что параметры в matrix() можно разделять запятой или пробелом. Однако при установке атрибута transform="matrix(...)" некоторые браузеры (Opera, Safari, Chrome и IE) сохраняют его, используя пробелы при разделении параметров.
Firefox сохраняет так,как записано.
var x=pmatrix2("matrix(1,0,1,1,0,0)","matrix(1,0,0,1,50,70)");
document.getElementById("mypicture").setAttribute("transform",x);
Следующий код показывает растровую картинку и строку текста.
В исходном состоянии картинка масштабирована с коэффициентом 0.6 и помещена в точку с координатами x=120px y=120px. Щелчок мышью на картинке с помощью функции pmatrix2() поворачивает ее на 30 градусов по часовой стрелке.
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="350"
xmlns:xlink="http://www.w3.org/1999/xlink">
<script type="text/javascript">
<![CDATA[
function pmatrix2(s1,s2){
// код (см. выше)
}
function imgrotate(){ // поворачиваем на 30 град.
var x=document.getElementById("myimg");
curattr=x.getAttribute("transform");
x.setAttribute("transform",
pmatrix2(curattr,"matrix(0.867,0.5,-0.5,0.867,0,0)"));
}
]]>
</script>
<image id="myimg"
transform="matrix(0.6 0 0 0.6 120 120)"
x="0" y="0" width="300" height="209" xlink:href="korabl16.jpg"
onclick="imgrotate()"
/>
<text x="10" y="300">
Щелчок на картинке поворачивает ее на 30 градусов
</text>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="350"
xmlns:xlink="http://www.w3.org/1999/xlink">
<script type="text/javascript">
<![CDATA[
function pmatrix2(s1,s2){
// код (см. выше)
}
<script type="text/javascript">
<![CDATA[
function imgflip(){
// отражаем относительно вертикали
var x=document.getElementById("myimg");
var curattr=x.getAttribute("transform");
x.setAttribute("transform",
pmatrix2(curattr,"matrix(-1 0 0 1 300 0)"))
}
]]>
</script>
< image id="myimg"
transform="matrix(0.7 0 0 0.7 20 20)"
x="0" y="0" width="300" height="209" xlink:href="korabl16.jpg"
onclick="imgflip()"
/>
< text x="5" y="200">
Щелчок на картинке отражает ее относительно вертикали
</text>
</svg>
Примечание
В CSS3 для аналогичных трансформаций имеется параметр transform.