#drag-and-drop #svg #translation #coordinates #coordinate-transformation
#перетаскивание #svg #перевод #координаты #преобразование координат
Вопрос:
Я должен выполнить групповой перевод (SVG) по определенной причине. Я не знаю, почему я не могу сделать это правильно, потому что после того, как перевод выполнен, при другом щелчке по группе перевод сбрасывается на начальную позицию и заставляет меня дурачиться, бегая по холсту SVG. Я пишу пример barebone по ссылке: http://www.atarado.com/en/stripboard-layout-software/group-translation-problem.svg , и вот код:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<script><![CDATA[
function startMove(evt){
x1=evt.clientX;
y1=evt.clientY;
group=evt.target.parentNode;
group.setAttribute("onmousemove","moveIt(evt)");
}
function moveIt(evt){
dx=evt.clientX-x1;
dy=evt.clientY-y1;
group.setAttributeNS(null,"transform","translate(" dx ", " dy ")");
}
function drop(){
group.setAttributeNS(null, "onmousemove",null);
}
]]></script>
<rect x="0" y="0" width="100%" height="100%" fill="dodgerblue"/>
<g id="BC" transform="translate(0, 0)" onmousedown="startMove(evt)" onmouseup="drop()"><circle id="C" cx="60" cy="60" r="22" fill="lightgrey" stroke="black" stroke-width="8"/><circle id="B" cx="120" cy="60" r="22" fill="orange" stroke="black" stroke-width="8" /></g>
</svg>
Приветствуется любой желающий помочь.
Комментарии:
1. Возможно, вас заинтересует этот пример: phrogz.net/SVG/drag_under_transformation.xhtml
2. Спасибо за ваш пример, он очень поучительный.
Ответ №1:
Причина, по которой позиция группы сбрасывается при втором перемещении, заключается в том, что вы устанавливаете преобразование в перевод, (dx, dy)
равное разнице между позицией, с которой началось перемещение (x1, y1)
, и текущей позицией (evt.clientX, evt.clientY)
. Это означает, что когда вы нажимаете второй раз, и они слегка перемещают мышь, тогда dx и dy — это маленькие числа. Затем они используются для установки преобразования на что-то немного отклоняющееся от начальной позиции. Помните, что в любое время преобразование, применяемое к группе, должно описывать преобразование из начальной позиции группы.
Одним из способов устранения проблемы было бы сохранить общую дельту от всех перемещений, примененных к группе до сих пор, и использовать это накопленное (dx, dy)
для построения преобразования. Например:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<script><![CDATA[
function startMove(evt){
group=evt.target.parentNode;
x1=evt.clientX - group.$x;
y1=evt.clientY - group.$y;
group.setAttribute("onmousemove","moveIt(evt)");
}
function moveIt(evt){
dx=evt.clientX-x1;
dy=evt.clientY-y1;
group.setAttributeNS(null,"transform","translate(" dx ", " dy ")");
group.$x = dx;
group.$y = dy;
}
function drop(){
group.setAttributeNS(null, "onmousemove",null);
}
]]></script>
<rect x="0" y="0" width="100%" height="100%" fill="dodgerblue"/>
<g id="BC" transform="translate(0, 0)" onmousedown="startMove(evt)" onmouseup="drop()">
<circle id="C" cx="60" cy="60" r="22" fill="lightgrey" stroke="black" stroke-width="8"/>
<circle id="B" cx="120" cy="60" r="22" fill="orange" stroke="black" stroke-width="8" />
</g>
<script><![CDATA[
var group=document.getElementById("BC");
group.$x = 0;
group.$y = 0;
]]></script>
</svg>
Мы добавили два свойства к элементу группы: $x
и $y
для сохранения текущей позиции элемента (или накопленных дельт от всех перемещений до сих пор, в зависимости от того, как вы на это смотрите). Они инициализируются нулем в скрипте, расположенном после определения элемента с идентификатором «BC». Они обновляются moveIt()
и используются startMove()
. Поскольку мы вычитаем наши новые дельты ($x, $y)
из (x1, y1)
in startMove()
, эти новые дельты эффективно добавляются (dx, dy)
позже moveIt()
. Это гарантирует (dx, dy)
учет всех ходов на данный момент, а также текущего хода.
Комментарии:
1. Вы мне очень ясно объясняете. Вот и все. Большое вам спасибо.