Команды SVG getCTM
и/или getScreenCTM
могут быть тем, что вам нужно. (Я полагаю, что CTM означает «Текущая матрица преобразования».) Вы можете использовать их, например, извлекая элемент с помощью jQuery, удаляя окружающий объект jQuery и вызывая команду, например. $("#mySvgCircleId")[0].getScreenCTM()
. Оба они возвращают матричные объекты SVG. Оба предоставят вам матричную информацию, которая учитывает их собственные прямые преобразования, а также любые преобразования, которые были применены к любым родительским элементам svg, в которые вложены фигуры. Это похоже на то, что вы искали.
Обратите внимание, однако, что между этими двумя командами есть важные различия. Я демонстрирую некоторые из этих различий в приведенном ниже фрагменте кода. Там я показываю два элемента svg
, один с двумя красными прямоугольниками и один с двумя синими. Все прямоугольники имеют одинаковую ширину и высоту, но один прямоугольник каждого цвета остается непреобразованным, а другой вложен в три группы, преобразованные по-разному. Выходные данные показывают результаты матрицы, используя getCTM
и getScreenCTM
для каждого прямоугольника. Обратите внимание на следующее:
- И
getCTM
, и getScreenCTM
учитывают преобразования любых вмещающих элементов-предков, например. любые элементы группы g
, вплоть до окружающего элемента svg
. например Возвращаемые матрицы различаются для «untransformedRect1» и «transformedRect1» для обеих команд.
- На результаты
getCTM
не влияет расположение окружающего элемента svg
в его родительском элементе, в то время как на результаты getScreenCTM
влияет. например Результаты для 'untransformedRect1' и 'untransformedRect2' идентичны при использовании getCTM
, но различаются при использовании getScreenCTM
.
Могут быть дополнительные сложности, если, например, вы имеете дело с iframe, вложением элементов svg в другие элементы svg и т. д., которые я здесь не рассматриваю.
var infoType = "CTM";
show("Matrix Results from getCTM()");
show(getInfo(infoType, "untransformedRect1"));
show(getInfo(infoType, "transformedRect1"));
show(getInfo(infoType, "untransformedRect2"));
show(getInfo(infoType, "transformedRect2"));
show("<br />");
var infoType = "ScreenCTM";
show("Matrix Results from getScreenCTM()");
show(getInfo(infoType, "untransformedRect1"));
show(getInfo(infoType, "transformedRect1"));
show(getInfo(infoType, "untransformedRect2"));
show(getInfo(infoType, "transformedRect2"));
function getInfo(mtrx, id) {
var mtrx;
if (infoType === "CTM") {
var mtrx = $("#" + id)[0].getCTM();
} else if (infoType === "ScreenCTM") {
var mtrx = $("#" + id)[0].getScreenCTM();
}
var str =
r(mtrx.a) + ", " +
r(mtrx.b) + ", " +
r(mtrx.c) + ", " +
r(mtrx.d) + ", " +
r(mtrx.e) + ", " +
r(mtrx.f);
return id + ": matrix: " + str;
}
function r(num) {
return Math.round(num * 1000) / 1000;
}
function show(msg) {
document.write(msg + "<br />");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Depending on how you are viewing this, you may need to scroll down to see the matrix values.</p>
<div id="containerForSvgs">
<svg id="svg1" width="150" height="100">
<rect id="background1" width="300" height="200" fill="#eee" transform="translate(0,0)"></rect>
<rect id="untransformedRect1" width="20" height="10" fill="red"></rect>
<g id="group1A" transform="scale(2)">
<g id="group1B" transform="translate(40,20)">
<g id="group1C" transform="rotate(-15)">
<rect id="transformedRect1" width="20" height="10" fill="red"></rect>
</g>
</g>
</g>
</svg>
<br />
shift ===>
<svg id="svg2" width="150" height="100">
<rect id="background2" width="300" height="200" fill="#eee" transform="translate(0,0)"></rect>
<rect id="untransformedRect2" width="20" height="10" fill="blue"></rect>
<g id="group2A" transform="scale(2)">
<g id="group2B" transform="translate(40,20)">
<g id="group2C" transform="rotate(-15)">
<rect id="transformedRect2" width="20" height="10" fill="blue"></rect>
</g>
</g>
</g>
</svg>
</div>
<br />
ОБНОВЛЕНИЕ На самом деле, исследуя это, я немного углубился в спецификации SVG и обнаружил очень классную другую функцию, которая может оказаться еще более мощной для того, что вам нужно: getTransformToElement
. По сути, вы можете получить кумулятивную матрицу преобразования из любого элемента (который я назову target
) в любой из включающих его элементов (который я назову enclosing
) с помощью одной команды: target.getTransformToElement(enclosing)
.
Ниже я предоставил еще один фрагмент кода, демонстрирующий его поведение, с именованным идентификатором, который, надеюсь, прояснит, как он может иметь отношение к вашей ситуации. Фрагмент показывает, что target.getCTM()
по существу обеспечивает тот же результат, что и target.getTransformToElement(enclosingSvgElement)
. Кроме того, однако, он также показывает, что он более гибкий, поскольку может отображать преобразование от под-под-вложенного элемента к любому из его предков-охватывающих элементов на любом произвольном расстоянии. Более того, вы можете смотреть в любом направлении, например. как target.getTransformToElement(enclosing)
, так и enclosing.getTransformToElement(target)
, где одна будет матрицей, обратной другой (если я правильно понимаю свою математическую терминологию).
var svg = $("svg" )[0];
var grp1 = $("#grp1_formatting_of_entire_app" )[0];
var grp2 = $("#grp2_menus_and_buttons_and_stuff" )[0];
var grp3 = $("#grp3_main_drawing_canvas" )[0];
var grp4 = $("#grp4_some_intervening_group" )[0];
var shp1 = $("#shp1_the_shape_I_currently_care_about" )[0];
var grp5 = $("#grp5_a_lower_group_I_dont_currently_care_about")[0];
var shp1_CTM = shp1.getCTM();
var shp1_to_svg = shp1.getTransformToElement(svg);
var shp1_to_grp3 = shp1.getTransformToElement(grp3);
var grp3_to_shp1 = grp3.getTransformToElement(shp1);
document.write("<table>");
show("getCTM for shp1" , shp1_CTM );
show("getTransformToElement from shp1 to enclosing svg", shp1_to_svg );
show("getTransformToElement from shp1 to grp3" , shp1_to_grp3);
show("getTransformToElement from grp3 to shp1" , grp3_to_shp1);
document.write("</table>");
function show(msg, mtrx) {
document.write("<tr><td>" + msg + "</td><td>" + mtrxStr(mtrx) + "</td></tr>");
}
function mtrxStr(mtrx) {
return "( " +
rnd(mtrx.a) + ", " +
rnd(mtrx.b) + ", " +
rnd(mtrx.c) + ", " +
rnd(mtrx.d) + ", " +
rnd(mtrx.e) + ", " +
rnd(mtrx.f) + " )";
}
function rnd(n) {
return Math.round(n*10)/10;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg width="200" height="60">
<g id="grp1_formatting_of_entire_app" transform="translate(30.0, 0)">
<g id="grp2_menus_and_buttons_and_stuff" transform="translate(10.0, 0)">
<g id="grp3_main_drawing_canvas" transform="translate( 3.0, 0)">
<g id="grp4_some_intervening_group" transform="translate( 1.0, 0)">
<rect id="shp1_the_shape_I_currently_care_about" transform="translate( 0.3, 0)"
x="0" y="0" width="100" height="40" fill="red"></rect>
<g id="grp5_a_lower_group_I_dont_currently_care_about" transform="translate( 0.1, 0)">
</g>
</g>
</g>
</g>
</g>
</svg>
<p>Results</p>
person
Andrew Willems
schedule
13.02.2016