Как анимировать SVG полигон для заполнения? - PullRequest
3 голосов
/ 10 апреля 2019

У меня есть буква 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 ]

6 голосов
/ 10 апреля 2019

Вы все еще можете нарисовать букву (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>
4 голосов
/ 10 апреля 2019

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>
2 голосов
/ 10 апреля 2019

Я решил это с помощью ключевых кадров 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-delay и animation-duration.

1 голос
/ 10 апреля 2019

Бонусная версия. Здесь я превратил ваши пути в маску и добавил фоновую анимацию.

enter image description here

<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 голос
/ 10 апреля 2019

Вот пример с чистым 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 голосов
/ 10 апреля 2019

Вы действительно можете использовать ключевые кадры, там есть много вещей, которые нужно сделать, кроме только непрозрачности.Вы можете анимировать рисование контуров с помощью stroke-dashoffset и stroke-dasharray.Есть также способы, позволяющие им постепенно исчезать, используя translateX или translateY.Также анимация вращения.взгляните на css в ручке, которую я сделал: https://codepen.io/YilmazTut/pen/JzaQEy.

также есть серия статей о svg из трюков css: https://css -tricks.com / lodge / svg/ Я использовал это, чтобы создать логотип в моей ручке.Примерно из урока 16 он объясняет, как работает анимация, а затем и рисование контуров.Я надеюсь, что вы можете найти свой путь там!

...