如何为SVG多边形添加填充动画?

4

我有一个由两个多边形和一个矩形组成的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

6个回答

7
您仍然可以使用描边的多边形来绘制(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>


1
感受到大师的手,可惜最近你很少回应。 - Alexandr_TT
1
@Alexandr_TT 很好的评论,谢谢 :) - web-tiki
我研究了你的旧作品,非常喜欢它们,并将许多内容翻译成俄语。当然,我总是指向原始来源。 - Alexandr_TT
非常好,完全按照我的要求工作!非常感谢你,伙计!非常感激! - Muktadir Anzan

6

奖励版本。在这里,我将你的路径转换为蒙版,并添加了背景动画。

输入图片描述

<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>


1
这很热门... - Justin

4

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>


1
动画化 fill-opacity 是最佳选择。 - enxaneta
嘿,老兄!你的回答对我来说几乎完美,但 web-tiki 发布了完美的答案。不过还是非常感谢你的回答,兄弟! - Muktadir Anzan

2
我使用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的值。

最初的回答

1
这是一个使用纯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>


0

你确实可以使用关键帧,除了不透明度之外还有很多其他事情可以做。你可以使用 stroke-dashoffsetstroke-dasharray 来动画绘制轮廓线。还可以使用 translateXtranslateY 让它们从左右淡入。还有旋转动画。

看看我制作的代码片段中的 CSS:https://codepen.io/YilmazTut/pen/JzaQEy

此外,CSS Tricks 上有一个关于 SVG 的系列文章:https://css-tricks.com/lodge/svg/。我用它来创建了代码片段中的标志。从第 16 个教程开始讲解如何制作动画,以及后来的路径绘制等。希望你能在这里找到自己的方向!


我也可以尝试为您的SVG创建一些内容,但是我需要您更具体地说明它需要如何进行动画处理。 - Yilmaz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接