动态动画 svg 元素

Dynamically animate an svg element

我正在实现一个简单的游戏,玩家要控制屏幕中间的一个红色圆圈。圆作为 SVG 元素实现。

我希望能够使用 SVG 动画 (SMIL) 在 SVG viewBox 中的任意两个位置之间移动圆圈。每个动画的触发器是左键单击屏幕上的任意位置。

我已经 written code,我相信它应该可以在 Firefox 和 Chrome 中使用。在 Chrome 中,它仅适用于第一个动画,而对于所有后续动画,圆仅适用于 "teleports"。在 Firefox 中没有动画 (并且控制台中没有错误).

我的代码中是否存在错误,或者 SMIL 是否过于不成熟是否存在一些众所周知的问题?

我能否让 SMIL 在此用例中工作,还是应该改用 canvas?

这是我目前得到的代码:

<!DOCTYPE html>
<html>
  <body>
    <svg id="canvas" width="800" height="800" onclick="Move()">
      <circle id="player1" cx="300" cy="300" r="40" stroke="blue" stroke-width="4" fill="red">
      </circle>
    </svg>
    <script>

      function createAnimation(attribute, playerID, duration, from, to) {
        var animation = document.createElementNS("http://www.w3.org/2000/svg", "animate")
        animation.setAttribute("attributeType", "XML")
        animation.setAttribute("attributeName", attribute)
        animation.setAttribute("dur", duration)
        animation.setAttribute("to", to)
        animation.setAttribute("from", from)
        animation.setAttribute("fill", "freeze")
        animationID = playerID + "animation" + attribute
        animation.setAttribute("id", animationID)
        player = document.getElementById(playerID)
        previous_animation = document.getElementById(animationID)
        if (previous_animation != null) {
          player.removeChild(previous_animation)
        }
        player.appendChild(animation)
      }

      function Move() {
        console.log(event.clientX);
        console.log(event.clientY);
        createAnimation("cx", "player1", "2s", document.getElementById("player1").getAttribute("cx"), event.clientX);
        createAnimation("cy", "player1", "2s", document.getElementById("player1").getAttribute("cy"), event.clientY);
      }

    </script>
  </body>

</html>

有很多问题...

  • Firefox 中没有事件(或更确切地说是 evt)对象,除非您从调用者那里传递一个对象。此错误确实出现在 Firefox 浏览器控制台中。
  • Firefox 仍然实现了 SVG 1.1 动画,它不会更新属性值,您需要调用 animVal 来获取值
  • 动画一次后,时间轴现在为 2 秒,因此下次您在 2 秒的文档中为 0-2 秒的动画制作动画时,它会跳到那里。每当下面的答案有变动时,我都会将时间轴重置为 0。

<!DOCTYPE html>
<html>
  <body>
    <svg id="canvas" width="800" height="800" onclick="Move(evt)">
      <circle id="player1" cx="300" cy="300" r="40" stroke="blue" stroke-width="4" fill="red">
      </circle>
    </svg>
    <script>
    
      function createAnimation(attribute, playerID, duration, from, to) {
        var animation = document.createElementNS("http://www.w3.org/2000/svg", "animate")
        animation.setAttribute("attributeType", "XML")
        animation.setAttribute("attributeName", attribute)
        animation.setAttribute("dur", duration)
        animation.setAttribute("to", to)
        animation.setAttribute("from", from)
        animation.setAttribute("fill", "freeze")
        animationID = playerID + "animation" + attribute
        animation.setAttribute("id", animationID)
        player = document.getElementById(playerID)
        previous_animation = document.getElementById(animationID)
        if (previous_animation != null) {
          player.removeChild(previous_animation)
        }
        player.appendChild(animation)
      }

      function Move(evt) {
        console.log(evt.clientX);
        console.log(evt.clientY);
        createAnimation("cx", "player1", "2s", document.getElementById("player1").cx.animVal.value, evt.clientX);
        createAnimation("cy", "player1", "2s", document.getElementById("player1").cy.animVal.value, evt.clientY);
        document.getElementById("canvas").setCurrentTime(0);
      }

    </script>
  </body>

</html>