SVG组平移问题

3

由于某些特殊原因,我需要进行组翻译(SVG)。但是我不知道为什么无法正确地进行翻译,因为在翻译完成后,当我再次点击组时,它会重置到起始位置,让我在SVG画布上四处奔波。

我在链接中提供了一个简单的示例: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>

欢迎任何愿意帮助的人。

2
你可能会对这个例子感兴趣:http://phrogz.net/SVG/drag_under_transformation.xhtml - Phrogz
谢谢您的示例,它非常有教育意义。 - Alex
1个回答

5
第二次移动时群组位置重置的原因是您将变换设置为平移,(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,用于存储元素的当前位置(或者是到目前为止所有移动的累积增量,这取决于您的观察方式)。在定义ID为“BC”的元素之后的脚本中,它们被初始化为零。它们在moveIt()中更新,并在startMove()中使用。由于我们在startMove()中从(x1, y1)中减去新的增量($x, $y),所以这些新的增量实际上会在moveIt()中后续添加到(dx, dy)中。这确保了(dx, dy)不仅考虑了到目前为止的所有移动,还包括了当前移动。

你让我非常清楚明白了。就是这样。非常感谢你。 - Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接