旋转后移动SVG元素

时间:2016-09-30 13:25:57

标签: javascript svg

请帮助我理解使用普通javascript操作svg元素及其变换的最佳实践。

我理解坐标系是在节点和链接等下传递的。

我想要实现的是在旋转后继续对元素进行原始翻译。在应用旋转后不沿轴。

我是否必须克隆复制第一个translate-transform并将其添加到转换列表的末尾?

非常感谢,如果有人能够以雄辩的方式阐明。

2 个答案:

答案 0 :(得分:3)

实现这一目标的方法是嵌套转换。例如,请查看以下示例SVG。



<svg width="600" height="200">
  <g>
    <rect x="0" y="50" width="100" height="100" fill="blue"/>
  </g>
</svg>
&#13;
&#13;
&#13;

您可以将一个转换应用于<g>,将另一个转换应用于<rect>。它们将是独立的,但将结合起来以实现整体效果。

因此,例如,如果我想将所有内容都移动,我可以将转换变换应用于该组。

&#13;
&#13;
<svg width="600" height="200">
  <g transform="translate(200,0)">
    <rect x="0" y="50" width="100" height="100" fill="blue"/>
  </g>
</svg>
&#13;
&#13;
&#13;

然后,如果我想将矩形旋转到位,我可以通过对其应用旋转变换来实现。

&#13;
&#13;
<svg width="600" height="200">
  <g transform="translate(200,0)">
    <rect x="0" y="50" width="100" height="100" fill="blue"
          transform="rotate(45,50,100)"/>
  </g>
</svg>
&#13;
&#13;
&#13;

然后,如果我想,我可以通过更新组的转换来进一步向右移动矩形。

&#13;
&#13;
<svg width="600" height="200">
  <g transform="translate(400,0)">
    <rect x="0" y="50" width="100" height="100" fill="blue"
          transform="rotate(45,50,100)"/>
  </g>
</svg>
&#13;
&#13;
&#13;

考虑这一点的方法是<rect>在其自己的小世界中(&#34;坐标空间&#34;是官方术语:)并且幸福地没有意识到什么是继续在其父元素。

因此,如果我们使用上面学到的东西,我们可以轻松创建您所追求的动画类型。以下动画包含三个阶段。首先我们向右移动矩形,然后我们旋转它,然后我们继续向右移动。中间的旋转不会影响我们再次向右移动的第三阶段。

&#13;
&#13;
var  outer = document.getElementById("outer");
var  inner = document.getElementById("inner");

var  tx = 0;     // the animated X position
var  angle = 0;  // the animated angle

/*
 * The first phase of the animation.
 * Function to step to the right until we hit tx=200.
 */
var  stepRightTo200 = function() {
  setTimeout(function() {
    tx += 4;
    outer.setAttribute('transform', 'translate('+tx+',0)');
    if (tx < 200)  // schedule another step in this phase
      stepRightTo200();
    else           // start next phase of animation
      rotateTo45();
  }, 32);
};

/*
 * The second phase of the animation.
 * Step the angle around until we hit 45 degrees.
 */
var  rotateTo45 = function() {
  setTimeout(function() {
    angle += 1;
    inner.setAttribute('transform', 'rotate('+angle+',50,100)');
    if (angle < 45)
      rotateTo45()
    else
      stepRightTo400();   // start third phase of animation
  }, 32);
};

/*
 * The third phase of the animation.
 * Step to the right until we hit tx=400.
 */
var  stepRightTo400 = function() {
  setTimeout(function() {
    tx += 4;
    outer.setAttribute('transform', 'translate('+tx+',0)');
    if (tx < 400)
      stepRightTo400();
  }, 32);
};

// Kick off first phase of animation
stepRightTo200();
&#13;
<svg width="600" height="200">
  <g id="outer">
    <rect id="inner" x="0" y="50" width="100" height="100" fill="blue"/>
  </g>
</svg>
&#13;
&#13;
&#13;

在上面的示例中,我将&#34;外部&#34;转变为父母群体,但我们并非真的必须这样做。我们可以将变换操作嵌套到单个变换中。

因此我们可以将上面的第三个SVG示例简化为:

&#13;
&#13;
<svg width="600" height="200">
  <rect x="0" y="50" width="100" height="100" fill="blue"
        transform="translate(400,0) rotate(45,50,100)"/>
</svg>
&#13;
&#13;
&#13;

&#34;外部&#34;变换成为变换列表中的第一个变换。如果您需要创建多部分转换,这是构建多部分转换的好方法。首先创建(或想象)嵌套的组结构,然后将转换应用于来自&#34;外部&#34; (左)到&#34;里面&#34; (右)。

最后,我们可以使用这种非嵌套形式重写动画脚本。

&#13;
&#13;
var  inner = document.getElementById("inner");

var  tx = 0;     // the animated X position
var  angle = 0;  // the animated angle

/*
 * The first phase of the animation.
 * Function to step to the right until we hit tx=200.
 */
var  stepRightTo200 = function() {
  setTimeout(function() {
    tx += 4;
    inner.setAttribute('transform',
                       'translate('+tx+',0) rotate('+angle+',50,100)');
    if (tx < 200)  // schedule another step in this phase
      stepRightTo200();
    else           // start next phase of animation
      rotateTo45();
  }, 32);
};

/*
 * The second phase of the animation.
 * Step the angle around until we hit 45 degrees.
 */
var  rotateTo45 = function() {
  setTimeout(function() {
    angle += 1;
    inner.setAttribute('transform',
                       'translate('+tx+',0) rotate('+angle+',50,100)');
    if (angle < 45)
      rotateTo45()
    else
      stepRightTo400();   // start third phase of animation
  }, 32);
};

/*
 * The third phase of the animation.
 * Step to the right until we hit tx=400.
 */
var  stepRightTo400 = function() {
  setTimeout(function() {
    tx += 4;
    inner.setAttribute('transform',
                       'translate('+tx+',0) rotate('+angle+',50,100)');
    if (tx < 400)
      stepRightTo400();
  }, 32);
};

// Kick off first phase of animation
stepRightTo200();
&#13;
<svg width="600" height="200">
  <rect id="inner" x="0" y="50" width="100" height="100" fill="blue"/>
</svg>
&#13;
&#13;
&#13;

希望这可以帮助您了解转换的工作原理。

答案 1 :(得分:1)

最好的方法是创建矩阵变换,然后请求各种变换并使用consolidate()方法。以下是一个例子

&#13;
&#13;
SELECT 
  tkoh.ticketid,
  tkoh.ownergroup,
  tkoh.owndate,
  tck.ACTUALFINISH,

  coalesce(datediff(day, tkoh.owndate, lead(tkoh.owndate) over(order by tkoh.ticketid, tkoh.owndate)),
     datediff(day, tkoh.owndate, tck.ACTUALFINISH)) As Diff

FROM tkownerhistory tkoh
LEFT JOIN ticket tck on tck.ticketid = tkoh.ticketid
WHERE tkoh.ticketid IN ('О1253565', 'О1253578') and tkoh.ownergroup is   not null
ORDER BY tkoh.ticketid, tkoh.owndate;
&#13;
&#13;
&#13;