【问题标题】:How to animate a SVG polygon to fill?如何为 SVG 多边形设置动画以进行填充?
【发布时间】:2019-08-31 18:04:39
【问题描述】:

我有一个 SVG 字母 (A),它由两个多边形和一个矩形组成。我想以 第一个多边形变为可见然后第二个多边形的方式为它们设置动画。之后,矩形将变得可见。在动画开始之前,SVG 将不可见。

我已经尝试过关键帧描边,但由于它们不是基于路径而是基于多边形的点,所以它不起作用。

<svg height="600" width="800">
  <polygon  points="34 537,150 536,289 130,314 53,196 51"/>
    <animate attributeName="points" dur="5s" fill="freeze"  />
  
   <polygon  points="411 537,528 537,364 118,354 91,348 72,341 53,327 53,223 55"/>
   <rect x="120" y="320"  stroke-miterlimit="10" width="270" height="120"/>
 </svg>

如果你想用,这里有一支笔:https://codepen.io/anon/pen/vMxXaP

【问题讨论】:

    标签: html css animation svg css-animations


    【解决方案1】:

    SVG 解决方案

    旋转和外观动画

    .container {
     width:35%;
     height:35%;
     }
    <div class="container">
    
    <svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
        xmlns:xlink="http://www.w3.org/1999/xlink"  viewBox="0 0 600 800">
      <g fill="black" fill-opacity="0" >
        <polygon
    	     id="left" transform="rotate(72 306 200)"  points="34 537,150 536,289 130,314 53,196 51"> 
             <animateTransform
    		 attributeName="transform"
    		 type="rotate"
    		 values="72 306 200;0 306 200"
    		 begin="svg1.click"
    		 dur="0.5s"
    		 fill="freeze" />  
    	 <animate
    	   id="an_op1"
    	   attributeName="fill-opacity"
    	   from="0"
    	   to="1"
    	   begin="svg1.click"
    	   dur="0.5s"
    	   fill="freeze" /> 
    	</polygon>	 
        <polygon id="right"  transform="rotate(-69 457.5 200)" 
    	       points="411 537,528 537,364 118,354 91,348 72,341 53,327 53,223 55">
    	 <animateTransform
    	     attributeName="transform"
    		 type="rotate"
    		 values="-69 457.5 200;0 457.5 200" 
    		 begin="an_op1.end"
    		 dur="0.5s"
    		 fill="freeze" />  
    	 <animate
    	    id="an_op2"
    		attributeName="fill-opacity"
    		from="0"
    		to="1"
    		begin="an_op1.end"
    		dur="0.5s"
    		fill="freeze" />
    	</polygon> 	 
            <rect id="rect1"  x="800" y="320"    width="270" height="120"> 
              <animate
    			  attributeName="x"
    			  from="800"
    			  to="120"
    			  begin="an_op2.end"
    			  dur="0.5s"
    			  fill="freeze" /> 
    		    <animate
    			  id="an_op3"
    			  attributeName="fill-opacity"
    			  from="0"
    			  to="1"
    			  begin="an_op2.end"
    			  dur="0.5s"
    			  fill="freeze" />
    	    </rect> 	  	
       </g>  
          <text x="0" y="80" font-size="50" fill="purple">Click me</text>
    </svg>
    </div>

    第二种解决方案

    所有动画元素在开始时都是不可见的。 fill-opacity="0"

    物品外观动画:

    <animate
          id="an_left"
          attributeName="fill-opacity"
          begin="1s"
          from="0"
          to="1"
          dur="0.3s"
          fill="freeze"/>
    

    以下是完整代码:

    .container {
    width:35%;
    height:35%;
    }
    <div class="container">
    <svg  version="1.1" xmlns="http://www.w3.org/2000/svg" 
        xmlns:xlink="http://www.w3.org/1999/xlink"  viewBox="0 0 600 800">
      
        <polygon id="right" fill="#008080" fill-opacity="0" 
    	   points="411 537,528 537,364 118,354 91,348 72,341 53,327 53,223 55">
    	   <animate
    	     id="an_right"
    		 attributeName="fill-opacity"
    		 begin="an_left.end"
    		 from="0"
    		 to="1"
    		 dur="0.3s"
    		 fill="freeze"/>
    	</polygon>   
    
     <polygon  id="left" fill="#008080" fill-opacity="0" points="34 537,150 536,289 130,314 53,196 51">
    	  <animate
    	  id="an_left"
    	  attributeName="fill-opacity"
    	  begin="0.2s"
    	  from="0"
    	  to="1"
    	  dur="0.3s"
    	  fill="freeze"/>
    	 </polygon> 
    
        <rect x="120" y="320" fill="#008080" fill-opacity="0" stroke-miterlimit="10" width="270" height="120"> 
    	    <animate
    		id="an_rect"
    		attributeName="fill-opacity"
    		from="0"
    		to="1"
    		begin="an_right.end"
    		dur="0.3s"
    		fill="freeze"/>
    	</rect> 
    </svg>
    </div>

    动画的顺序是通过属性中的一连串条件实现的——begin="an_left.end"

    这样的记录意味着右侧矩形的动画将在左侧多边形的动画结束之后才开始。

    CSS 解决方案

    .container {
    width:35%;
    height:35%;
    }
    #left,#right,  #rect1 {
    fill-opacity:0;
    fill:#008080;
    
    }
    #left {
    animation:anLeft  0.3s ease forwards;
    animation-delay: 0.1s;
    }
    
    @keyframes anLeft {
      100% {
        fill-opacity:1;
    	
      }
    } 
    #right {
    animation:anRight  0.3s ease forwards;
    animation-delay: 0.4s;
    }
    
    @keyframes anRight {
      100% {
        fill-opacity:1;
      }
    }  
    
    #rect1 {
    animation:anRect  0.3s ease forwards;
    animation-delay:0.7s;
    }
    
    @keyframes anRect {
      100% {
        fill-opacity:1;
      }
    }
    <div class="container">
    <svg  version="1.1" xmlns="http://www.w3.org/2000/svg" 
        xmlns:xlink="http://www.w3.org/1999/xlink"  viewBox="0 0 600 800">
      
        <polygon id="right"  
    	   points="411 537,528 537,364 118,354 91,348 72,341 53,327 53,223 55"/>
     <polygon  id="left"  points="34 537,150 536,289 130,314 53,196 51"/>
        <rect id="rect1" x="120" y="320"  stroke-miterlimit="10" width="270" height="120"/> 
    </svg>
    </div>

    【讨论】:

    • 动画fill-opacity是最好的选择。
    • 嘿伙计!你的回答对我来说几乎是完美的,但 web-tiki 发布了一个完美的答案。不过非常感谢老哥的解答!
    【解决方案2】:

    奖金版本。在这里,我将您的路径变成了蒙版并添加了背景动画。

    <svg  version="1.1" xmlns="http://www.w3.org/2000/svg" 
        xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 600 800">
       <style>  
        svg {
          height:160px;
          background: url(https://i.imgur.com/Pr8tfnT.png);
          background-position: 0px 111px;
          background-repeat: repeat-x;
          background-size: 100%;
          animation: water 10s forwards;
        }
    
        @keyframes water {
          100% {
            background-position: 2000px 0px;
          }
        }
       </style>   
       <mask id="mask" fill="black">
        <rect fill="white" width="600" height="800"/>
        <polygon id="right" points="411 537,528 537,364 118,354 91,348 72,341 53,327 53,223 55"/>
        <polygon id="left"  points="34 537,150 536,289 130,314 53,196 51"/>
        <rect id="rect1" x="120" y="320"  stroke-miterlimit="10" width="270" height="120"/> 
       </mask>
    
       <rect fill="white" width="600" height="800" mask="url(#mask)"/>
    </svg>

    【讨论】:

      【解决方案3】:

      这是一个纯 javascript 的示例,并通过增量时间改变不透明度

      let left = document.querySelector('#left')
      let right = document.querySelector('#right')
      let rect1 = document.querySelector('#rect1')
      let time = 3000; // animation time
      let delay = 1000; // animation delay
      
      // dt - time from animation start
      function animate(dt) { 
       let v = dt - delay;  
       opacity(left, v/time*3);     
       opacity(right, v/time*3 - 1);
       opacity(rect1, v/time*3 - 2);
       dt < time + delay + 50 && requestAnimationFrame(animate)
      } 
      
      function opacity(el, v) {
       v = Math.min(1, Math.max(v, 0)); // clamp to 0-1
       el.setAttribute('opacity', v)
      }
      
      requestAnimationFrame(animate);
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <svg  version="1.1" xmlns="http://www.w3.org/2000/svg" 
          xmlns:xlink="http://www.w3.org/1999/xlink" height="175" viewBox="0 0 600 800">
        <g fill="#008080">
          <polygon id="right" opacity="0" points="411 537,528 537,364 118,354 91,348 72,341 53,327 53,223 55"/>
          <polygon id="left" opacity="0" points="34 537,150 536,289 130,314 53,196 51"/>
          <rect id="rect1" opacity="0" x="120" y="320"  stroke-miterlimit="10" width="270" height="120"/> 
         </g> 
      </svg>

      【讨论】:

        【解决方案4】:

        您仍然可以使用带笔触而不是填充的多边形来绘制 (A) 字母。以下示例使用 stroke-dasharray 上的两个关键帧动画分两步绘制 A 字母:

        1. 左上角和右上角线的第一步(svg 中的第一个多边形元素)
        2. 关闭 A 的水平线的第二步(svg 元素中的第二个多边形)

        .letter {
          width:200px;height:auto;
          stroke-width:2.5;
          stroke:#000;
          fill:none;
          stroke-dasharray: 0 24;
        }
        .animateFirst { animation: 0.5s animateFirst ease-in forwards; }
        .animateSecond { animation: 0.2s 0.45s animateSecond ease-out forwards; }
        
        @keyframes animateFirst {
          to { stroke-dasharray: 24 24; }
        }
        @keyframes animateSecond {
          to { stroke-dasharray: 6 24; }
        }
        <svg class="letter" viewbox="0 0 12 10">
          <polygon class="animateFirst" points="1,11.5 6,0 11,11.5" />
          <polygon class="animateSecond" points="3,6.5 9,6.5" />  
        </svg>

        【讨论】:

        • 感受大师之手 可惜你最近很少回复
        • @Alexandr_TT 这是一个非常好的评论,谢谢 :)
        • 我研究了你的旧作。我真的很喜欢他们,很多翻译成俄语。 SO 当然,我总是指出源头。
        • 完全按照我的要求工作!非常感谢你!非常感谢!
        【解决方案5】:

        我使用 CSS 关键帧解决了这个问题,这是您要找的吗?

            @keyframes fade {
              from {
                opacity: 0;
              }
              to {
                opacity: 1;
              }
            }
            
            #right {
              animation-delay: 1s;
            }
            
            #center {
              animation-delay: 2s;
            }
            
            .shape {
              opacity: 0;
              animation-fill-mode: forwards;
              animation-iteration-count: 1;
              animation-name: fade;
              animation-duration: 1s;
            }
        <svg id="abcdef" height="600" width="800">
              <polygon class="shape" points="34 537,150 536,289 130,314 53,196 51"/>
              <polygon id="right" class="shape" points="411 537,528 537,364 118,354 91,348 72,341 53,327 53,223 55"/>
              <rect id="center" class="shape"  x="120" y="320" filter="#008080" stroke-miterlimit="10" width="270" height="120"/>
            </svg>

        如果您想调整动画的持续时间,您必须考虑更改 animation-delayanimation-duration 的值。

        【讨论】:

          【解决方案6】:

          您确实可以使用关键帧,除了不透明度之外,还有很多事情要做。您可以使用stroke-dashoffsetstroke-dasharray 动画绘制轮廓。还有一些方法可以让它们从 let 和 right 淡入 translateXtranslateY。还有旋转动画。 看看我做的笔中的css:https://codepen.io/YilmazTut/pen/JzaQEy.

          还有一系列关于 svg 的 css 技巧:https://css-tricks.com/lodge/svg/ 我用它在我的笔中创建徽标。从教程 16 开始,他解释了动画以及路径绘图的工作原理。我希望你能找到你的路!

          【讨论】:

          • 我也可以尝试为你的 svg 创建一些东西,但我需要你更具体地说明它需要如何制作动画。
          猜你喜欢
          • 2020-10-14
          • 2017-08-22
          • 1970-01-01
          • 1970-01-01
          • 2015-04-12
          • 1970-01-01
          • 1970-01-01
          • 2020-09-19
          • 1970-01-01
          相关资源
          最近更新 更多