如何在SVG <use>元素中触发动画?

时间:2015-10-15 23:59:12

标签: javascript animation svg

我创建了一个简单的SVG动画,它是通过单击SVG元素触发的。我想多次重复使用这个动画元素,我希望每次都避免重复这个定义。但是,当我在<defs>标记内创建元素,然后使用<use>标记实现该元素时,我无法从外部访问动画。

下面是相同的动画元素的示例,它们都独立(黄色)并实现为<use>元素(橙色和红色)。唯一可行的动画是黄色动画。

我已经在g部分内定义的SVG <defs> roup中重复了动画,以表明动画可以正常工作。

有没有办法从外部触发<use>元素内的动画?或者是否有另一种方法可以在重用元素中创建双状态动画?

jsfiddle

<!DOCTYPE html>
<html>
<head>
  <title></title>
  <style>
    g#yellow {
      fill:#cc9;
      color: #993;
    }
    use#orange {
      fill: #ca8;
      color: #963;
    }
    use#red {
      fill:#c99;
      color:#933;
    }
  </style> 
</head>

<body>
<svg width="360" height="120" 
     viewPort="0 0 120 360" version="1.1"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">

<defs>
  <g
    id="door"
    width="120"
    height="120" 
    viewPort="0 0 120 120">

    <rect width="120" height="120" class="wall"></rect>
    <rect
      x="30"
      y="20"
      width="60"
      height="100"
      fill="#000"
      opacity="0.7"></rect>

    <polygon class="door"
      points="
  30,120
  90,120
  90,20
  30,20"
      fill="currentColor">
      <animate
        class="open"
        attributeName="points"
        dur="500ms"
        to="
  100,120
  90,120
  90,20
  100,10"
      begin="indefinite" 
      fill="freeze" />
      <animate
        class="shut"
        attributeName="points"
        dur="500ms"
        to="
  30,120
  90,120
  90,20
  30,20"
      begin="indefinite" 
      fill="freeze" />
     <animate
      attributeName="opacity"
      values="0.5;1;0.5" dur="2s"
      repeatCount="indefinite" />
    </polygon>
  </g>
</defs> 

  <use x="240" y="0" xlink:href="#door" id="red"/>
  <use x="120" y="0" xlink:href="#door" id="orange"/>
  <g xlink:href="#door" id="yellow"
    id="door"
    width="120"
    height="120" 
    viewPort="0 0 120 120">

    <rect width="120" height="120" class="wall"></rect>
    <rect
      x="30"
      y="20"
      width="60"
      height="100"
      fill="#000"
      opacity="0.7"></rect>

    <polygon class="door"
      points="
  30,120
  90,120
  90,20
  30,20"
      fill="currentColor">
      <animate
        class="open"
        attributeName="points"
        dur="500ms"
        to="
  100,120
  90,120
  90,20
  100,10"
      begin="indefinite" 
      fill="freeze" />
      <animate
        class="shut"
        attributeName="points"
        dur="500ms"
        to="
  30,120
  90,120
  90,20
  30,20"
      begin="indefinite" 
      fill="freeze" />
    </polygon>
  </g>
</svg>

<script>
;(function () {
  document.body.onclick = function(event) {
    var target = event.target
    var animation

    while (target && target.nodeName.toLowerCase() !== "g") {
      target = target.parentNode
    }

    if (!target) {
      return
    }

    if (target.classList.contains("open")) {
      target.classList.remove("open")
      animation=document.querySelector("#"+target.id+" animate.shut")
    } else {
      target.classList.add("open");
      animation=document.querySelector("#"+target.id+" animate.open")
    }

    animation.beginElement()
  }
})()
</script>
</body>
</html>

编辑:我尝试了另一种方法,我在其中定义了几个不同的g元素:

  • 没有动画的人
  • 一个开场动画
  • 一个结束动画

我使用JavaScript将href <use>元素交换到相应的g元素。

交换元素无法播放动画,在不同浏览器中具有不同的效果。在Chrome和Firefox中,新元素会立即显示在动画后状态中。在Apple Safari中,它们处于动画前的状态。

jsfiddle

0 个答案:

没有答案
相关问题