使用svg和javascript将一个类的元素动画化为另一个类

animate elements of one class to another class using svg and javascript?

本文关键字:元素 动画 另一个 一个 javascript svg 使用      更新时间:2023-09-26

我正试着从早上到中午,从下午到晚上制作一部动画。当用户输入早晨时,应该显示早晨的场景,然后为当天的剩余时间设置动画。同样,如果他进入下午,它应该显示下午,然后动画。我该怎么做?如何将一个类的属性设置为另一个类属性的动画?

<html>
<head>
</head>
<style>
form{
position:absolute;
top: 550px;
}
</style>
<body>
<svg width="800" height="800" border="1px">
<defs>
    <filter id="f1">
      <feGaussianBlur in="SourceGraphic" stdDeviation="4" />
    </filter>
  </defs>
<div class="morning">
<rect id="sky" x="0" y="0" width="800" height="150" style="fill: #E6FFF2; stroke: #80CCFF; stroke-width:3"/ >
 <rect id="ground" x="0" y="400" width="800" height="100" style="fill: #43BF43; stroke: #369936; stroke-width:3" />
 <rect id="branch1" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#993300; ; stroke-width:5"/>

      <ellipse id="tree1" cx="110" cy="280" rx="100" ry="50" style="fill:green; stroke:green; stroke-width:5" >
</ellipse>
      <rect id="branch2" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#993300 ; stroke-width:5" transform="translate(310)" >
      </rect>
      <ellipse id="tree2" cx="110" cy="280" rx="100" ry="50" style="fill:green; stroke:green; stroke-width:2" transform="translate(310)" 
             </ellipse>

     <rect id="branch3" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#993300 ; stroke-width:5" transform="translate(580)" >    
      </rect>
      <ellipse id="tree3" cx="110" cy="280" rx="100" ry="50" style="fill:green; stroke:green; stroke-width:5" transform="translate(580)">
      </ellipse>

      <circle id="sun" cx="60" cy="150" r="55" stroke="red" stroke-width="7" fill="orange" filter="url(#f1)"/>  
</div>
<div class="noon">
<rect id="sky" x="0" y="0" width="800" height="150" style="fill: #E6FFF2; stroke: #80CCFF; stroke-width:3" />
<rect id="ground" x="0" y="400" width="800" height="100" style="fill: #43BF43; stroke: #369936; stroke-width:3" />
 <rect id="branch1" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#993300; ; stroke-width:5"/>

      <ellipse id="tree1" cx="110" cy="280" rx="100" ry="50" style="fill:green; stroke:green; stroke-width:5" >
</ellipse>
      <rect id="branch2" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#993300 ; stroke-width:5" transform="translate(310)" >
      </rect>
      <ellipse id="tree2" cx="110" cy="280" rx="100" ry="50" style="fill:green; stroke:green; stroke-width:2" transform="translate(310)" 
             </ellipse>

     <rect id="branch3" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#993300 ; stroke-width:5" transform="translate(580)" >    
      </rect>
      <ellipse id="tree3" cx="110" cy="280" rx="100" ry="50" style="fill:green; stroke:green; stroke-width:5" transform="translate(580)">
      </ellipse>
      <circle id="sun" cx="350" cy="70" r="55" stroke="#E6E600" stroke-width="7" fill="yellow" filter="url(#f1)"/>  
</div>
<div class="afternoon">
<rect id="sky" x="0" y="0" width="800" height="150" style="fill: #E6FFF2; stroke: #80CCFF; stroke-width:3"/ >
<rect id="ground" x="0" y="400" width="800" height="100" style="fill: #43BF43; stroke: #369936; stroke-width:3" />
 <rect id="branch1" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#993300; ; stroke-width:5">

      <ellipse id="tree1" cx="110" cy="280" rx="100" ry="50" style="fill:green; stroke:green; stroke-width:5" >
</ellipse>
      <rect id="branch2" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#993300 ; stroke-width:5" transform="translate(310)" >
      </rect>
      <ellipse id="tree2" cx="110" cy="280" rx="100" ry="50" style="fill:green; stroke:green; stroke-width:2" transform="translate(310)" 
             </ellipse>

     <rect id="branch3" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#993300 ; stroke-width:5" transform="translate(580)" >    
      </rect>
      <ellipse id="tree3" cx="110" cy="280" rx="100" ry="50" style="fill:green; stroke:green; stroke-width:5" transform="translate(580)">
      </ellipse>
      <circle id="sun" cx="500" cy="100" r="55" stroke="#FF8533" stroke-width="7" fill="#FFA366" filter="url(#f1)"/>    
</div>
<div class="sunset">
<rect id="sky" x="0" y="0" width="800" height="150" style="fill: #993300; stroke: #E6B800; stroke-width:3" />
 <rect id="ground" x="0" y="400" width="800" height="100" style="fill: #993300; stroke: #E6B800; stroke-width:3"/ >
 <rect id="branch1" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#E6B800; ; stroke-width:5"/>
  <rect id="branch2" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#E6B800; ; stroke-width:5"/>
   <rect id="branch3" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#E6B800; ; stroke-width:5"/>
   <ellipse id="tree1" cx="110" cy="280" rx="100" ry="50" style="fill:#993300; stroke:#E6B800; stroke-width:5" />
      <ellipse id="tree2" cx="110" cy="280" rx="100" ry="50" style="fill:#993300; stroke:#E6B800; stroke-width:5" />
         <ellipse id="tree3" cx="110" cy="280" rx="100" ry="50" style="fill:#993300; stroke:#E6B800; stroke-width:5" />
              <circle id="sun" cx="800" cy="150" r="55" stroke="FF7070" stroke-width="7" fill="red" filter="url(#f1)"/>
</div>
</svg>
<form>
Enter Time:<input type="text" id="text"><br/>
<input type="button" id="button" value="show">
</form>
</body>
</html> 

这就是动画的工作方式,无需用户输入:

<!DOCTYPE html>
<html>
<head>
<script>
</script>
</head>
<style>
form{
position:absolute;
top: 550px;
}
</style>
<body>

<svg width="800" height="800" border="1px">
<defs>
    <filter id="f1">
      <feGaussianBlur in="SourceGraphic" stdDeviation="4" />
    </filter>
  </defs>

  <rect id="sky" x="0" y="0" width="800" height="150" style="fill: #E6FFF2; stroke: #80CCFF; stroke-width:3" >
  <animate attributeName="stroke" attributeType="CSS" from="#80CCFF"  to="#E6B800" begin="10s" dur="5s" />
      <animate attributeName="fill" attributeType="CSS" from="#E6FFF2"  to="#993300" begin="10s" dur="5s" />
      </rect>

    <rect id="ground" x="0" y="400" width="800" height="100" style="fill: #43BF43; stroke: #369936; stroke-width:3" >
    <animate attributeName="stroke" attributeType="CSS" from="#369936"  to="#E6B800" begin="10s" dur="5s" />
      <animate attributeName="fill" attributeType="CSS" from="#43BF43"  to="#993300" begin="10s" dur="5s" />
      </rect>
      <rect id="branch1" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#993300; ; stroke-width:5">
      <animate attributeName="stroke" attributeType="CSS" from="#993300"  to="#E6B800" begin="10s" dur="5s" />
      </rect>

      <ellipse id="tree1" cx="110" cy="280" rx="100" ry="50" style="fill:green; stroke:green; stroke-width:5" >
      <animate attributeName="stroke" attributeType="CSS" from="green"  to="#E6B800" begin="10s" dur="5s" />
      <animate attributeName="fill" attributeType="CSS" from="green"  to="#993300" begin="10s" dur="5s" />
</ellipse>
      <rect id="branch2" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#993300 ; stroke-width:5" transform="translate(310)" >
      <animate attributeName="stroke" attributeType="CSS" from="#993300"  to="#E6B800" begin="10s" dur="5s" />
      </rect>
      <ellipse id="tree2" cx="110" cy="280" rx="100" ry="50" style="fill:green; stroke:green; stroke-width:2" transform="translate(310)" >
<animate attributeName="stroke" attributeType="CSS" from="green"  to="#E6B800" begin="10s" dur="5s" />
      <animate attributeName="fill" attributeType="CSS" from="green"  to="#993300" begin="10s" dur="5s" />
             </ellipse>

     <rect id="branch3" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#993300 ; stroke-width:5" transform="translate(580)" >    
<animate attributeName="stroke" attributeType="CSS" from="#993300"  to="#E6B800" begin="10s" dur="5s" />
      </rect>
      <ellipse id="tree3" cx="110" cy="280" rx="100" ry="50" style="fill:green; stroke:green; stroke-width:5" transform="translate(580)">
      <animate attributeName="stroke" attributeType="CSS" from="green"  to="#E6B800" begin="10s" dur="5s" />
      <animate attributeName="fill" attributeType="CSS" from="green"  to="#993300" begin="10s" dur="5s" />  
      </ellipse>

      <circle id="sun" cx="60" cy="150" r="55" stroke="red" stroke-width="7" fill="orange" filter="url(#f1)">     //morning

          <animate attributeName="cx" attributeType="XML"
             from="60"  to="350"
             begin="0s" dur="5s"
             />
             <animate attributeName="cy" attributeType="XML"
             from="150"  to="70"
             begin="0s" dur="5s"
             />
        <animate attributeName="cx" attributeType="XML"
             from="350"  to="500"
             begin="5s" dur="5s"
             />
                  <animate attributeName="cy" attributeType="XML"
             from="70"  to="100"
             begin="5s" dur="5s"
             />
      <animate attributeName="cx" attributeType="XML"
             from="500"  to="800"
             begin="10s" dur="5s"
             />
                  <animate attributeName="cy" attributeType="XML"
             from="100"  to="150"
             begin="10s" dur="5s"
             />

      <animate attributeName="fill" attributeType="XML"
       from="orange" to="yellow"  begin="0s" dur="5s" />   //noon
      <animate attributeName="stroke" attributeType="XML"
       from="red" to="#E6E600"  begin="0s" dur="5s" /> //noon
        <animate attributeName="fill" attributeType="XML"
       from="yellow" to="#FFA366"  begin="5s" dur="5s" />      //afternoon
       <animate attributeName="stroke" attributeType="XML"
       from="#E6E600" to="#FF8533"  begin="5s" dur="5s" /> //afternoon
            <animate attributeName="fill" attributeType="XML"
       from="#FFA366" to="red"  begin="10s" dur="5s" /> //evening
           <animate attributeName="stroke" attributeType="XML"
       from="#FF8533" to="#FF7070"  begin="10s" dur="5s"  /> //evening

       </circle>

</svg>
<form>
Enter Time:<input type="text" id="text"><br/>
<input type="button" id="button" value="show">
</form>
</body>
</html> 

除了将属性begin设置为"indefinite"之外,还可以使用SMIL Animation的beginElement()方法来触发动画
为了更容易从js访问,我还将它们按类分组。

Javascript:

document.getElementById('button').addEventListener('click', triggerAnim, false);
function triggerAnim(){
  var time = document.getElementById('text').value;
  var els = document.querySelector('svg').querySelectorAll('animate.'+time);
  for(var i=0; i<els.length; i++){
      els[i].beginElement();
    }
  }

SVG

<animate class="noon" attributeName="stroke" attributeType="XML"
       from="#E6E600" to="#FF8533"  begin="indefinite" dur="5s" fill="freeze" /> 

我添加了属性fill="freeze",以在动画完成后保留修改,但这样做,您还必须为只有"晚间"角色在表演时创建新的<animate>,以便从第一个值重新开始。

<!DOCTYPE html>
<html>
<head>
</head>
<style>
form{
position:absolute;
top: 550px;
}
</style>
<body>
<svg width="800" height="800" border="1px">
<defs>
    <filter id="f1">
      <feGaussianBlur in="SourceGraphic" stdDeviation="4" />
    </filter>
  </defs>
  <rect id="sky" x="0" y="0" width="800" height="150" style="fill: #E6FFF2; stroke: #80CCFF; stroke-width:3" >
	  <animate class="morning noon" attributeName="stroke" attributeType="CSS" from="indefinite"  to="#80CCFF" begin="indefinite" dur="5s" fill="freeze" />
      <animate class="morning noon" attributeName="fill" attributeType="CSS" from="indefinite"  to="#E6FFF2" begin="indefinite" dur="5s" fill="freeze" />
  	  <animate class="evening" attributeName="stroke" attributeType="CSS" from="#80CCFF"  to="#E6B800" begin="indefinite" dur="5s" fill="freeze" />
      <animate class="evening" attributeName="fill" attributeType="CSS" from="#E6FFF2"  to="#993300" begin="indefinite" dur="5s" fill="freeze" />
      </rect>
    <rect id="ground" x="0" y="400" width="800" height="100" style="fill: #43BF43; stroke: #369936; stroke-width:3" >
	  <animate class="morning noon" attributeName="stroke" attributeType="CSS" from="indefinite"  to="#369936" begin="indefinite" dur="5s" fill="freeze" />
      <animate class="morning noon" attributeName="fill" attributeType="CSS" from="indefinite"  to="#43BF43" begin="indefinite" dur="5s" fill="freeze" />
	  <animate class="evening" attributeName="stroke" attributeType="CSS" from="#369936"  to="#E6B800" begin="indefinite" dur="5s" fill="freeze" />
      <animate class="evening" attributeName="fill" attributeType="CSS" from="#43BF43"  to="#993300" begin="indefinite" dur="5s" fill="freeze" />
      </rect>
      <rect id="branch1" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#993300; ; stroke-width:5">
      <animate class="morning noon" attributeName="stroke" attributeType="CSS" from="indefinite"  to="#993300" begin="indefinite" dur="5s" fill="freeze" />
      <animate class="evening" attributeName="stroke" attributeType="CSS" from="#993300"  to="#E6B800" begin="indefinite" dur="5s" fill="freeze" />
      </rect>
      <ellipse id="tree1" cx="110" cy="280" rx="100" ry="50" style="fill:green; stroke:green; stroke-width:5" >
      <animate class="morning noon" attributeName="stroke" attributeType="CSS" from="indefinite"  to="green" begin="indefinite" dur="5s" fill="freeze" />
      <animate class="morning noon" attributeName="fill" attributeType="CSS" from="indefinite"  to="green" begin="indefinite" dur="5s" fill="freeze" />
      <animate class="evening" attributeName="stroke" attributeType="CSS" from="green"  to="#E6B800" begin="indefinite" dur="5s" fill="freeze" />
      <animate class="evening" attributeName="fill" attributeType="CSS" from="green"  to="#993300" begin="indefinite" dur="5s" fill="freeze" />
</ellipse>
      <rect id="branch2" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#993300 ; stroke-width:5" transform="translate(310)" >
      <animate class="morning noon" attributeName="stroke" attributeType="CSS" from="indefinite"  to="#993300" begin="indefinite" dur="5s" fill="freeze" />
      <animate class="evening" attributeName="stroke" attributeType="CSS" from="#993300"  to="#E6B800" begin="indefinite" dur="5s" fill="freeze" />
      </rect>
      <ellipse id="tree2" cx="110" cy="280" rx="100" ry="50" style="fill:green; stroke:green; stroke-width:2" transform="translate(310)" >
      <animate class="morning noon" attributeName="stroke" attributeType="CSS" from="indefinite"  to="green" begin="indefinite" dur="5s" fill="freeze" />
      <animate class="morning noon"  attributeName="fill" attributeType="CSS" from="indefinite"  to="green" begin="indefinite" dur="5s" fill="freeze" />
	  <animate class="evening" attributeName="stroke" attributeType="CSS" from="green"  to="#E6B800" begin="indefinite" dur="5s" fill="freeze" />
      <animate class="evening"  attributeName="fill" attributeType="CSS" from="green"  to="#993300" begin="indefinite" dur="5s" fill="freeze" />
             </ellipse>
     <rect id="branch3" x="55" y="315" width="50" height="150" style="fill: #993300; stroke:#993300 ; stroke-width:5" transform="translate(580)" >    
     <animate class="morning noon" attributeName="stroke" attributeType="CSS" from="indefinite"  to="#993300" begin="indefinite" dur="5s" fill="freeze" />
	 <animate class="evening" attributeName="stroke" attributeType="CSS" from="#993300"  to="#E6B800" begin="indefinite" dur="5s" fill="freeze" />
      </rect>
      <ellipse id="tree3" cx="110" cy="280" rx="100" ry="50" style="fill:green; stroke:green; stroke-width:5" transform="translate(580)">
      <animate class="morning noon" attributeName="stroke" attributeType="CSS" from="indefinite"  to="green" begin="indefinite" dur="5s" fill="freeze" />
      <animate class="morning noon" attributeName="fill" attributeType="CSS" from="indefinite"  to="green" begin="indefinite" dur="5s" fill="freeze" />  
      <animate class="evening" attributeName="stroke" attributeType="CSS" from="green"  to="#E6B800" begin="indefinite" dur="5s" fill="freeze" />
      <animate class="evening" attributeName="fill" attributeType="CSS" from="green"  to="#993300" begin="indefinite" dur="5s" fill="freeze" />  
      </ellipse>
      <circle id="sun" cx="60" cy="150" r="55" stroke="red" stroke-width="7" fill="orange" filter="url(#f1)">     //morning
        <animate class="morning" attributeName="cx" attributeType="XML"
             from="60"  to="350"
             begin="indefinite" dur="5s" fill="freeze"
             />
        <animate class="morning" attributeName="cy" attributeType="XML"
             from="150"  to="70"
             begin="indefinite" dur="5s" fill="freeze"
             />
        <animate class="noon" attributeName="cx" attributeType="XML"
             from="350"  to="500"
             begin="indefinite" dur="5s" fill="freeze"
             />
        <animate class="noon" attributeName="cy" attributeType="XML"
             from="70"  to="100"
             begin="indefinite" dur="5s" fill="freeze"
             />
      	<animate class="evening" attributeName="cx" attributeType="XML"
             from="500"  to="800"
             begin="indefinite" dur="5s" fill="freeze"
             />
        <animate class="evening" attributeName="cy" attributeType="XML"
             from="100"  to="150"
             begin="indefinite" dur="5s" fill="freeze"
             />
	    <animate class="morning" attributeName="fill" attributeType="XML"
	       from="orange" to="yellow"  begin="indefinite" dur="5s" fill="freeze" />   //noon
	    <animate class="morning" attributeName="stroke" attributeType="XML"
	       from="red" to="#E6E600"  begin="indefinite" dur="5s" fill="freeze" /> //noon
        <animate class="noon" attributeName="fill" attributeType="XML"
    	   from="yellow" to="#FFA366"  begin="indefinite"dur="5s" fill="freeze" />      //afternoon
        <animate class="noon" attributeName="stroke" attributeType="XML"
       	   from="#E6E600" to="#FF8533"  begin="indefinite" dur="5s" fill="freeze" /> //afternoon
    	<animate class="evening" attributeName="fill" attributeType="XML"
       	   from="#FFA366" to="red"  begin="indefinite"  dur="5s" fill="freeze" /> //evening
        <animate class="evening" attributeName="stroke" attributeType="XML"
           from="#FF8533" to="#FF7070"  begin="indefinite" dur="5s" fill="freeze"  /> //evening
       </circle>
</svg>
<form>
Enter Time:<input type="text" id="text"><br/>
<input type="button" id="button" value="show">
</form>
<script>
document.getElementById('button').addEventListener('click', triggerAnim, false);
function triggerAnim(){
    var time = document.getElementById('text').value;
    var els = document.querySelector('svg').querySelectorAll('animate.'+time);
  for(var i=0; i<els.length; i++){
      els[i].beginElement();
    }
  }
</script>
</body>
</html>