css – How to create a sequential SVG animation of the appearance of four stripes

Question:

The sequential animation of the appearance of the four stripes should follow the following scenario:

Animation script:

  1. The first top bar is drawn from left to right for 4 seconds
    2-4 p-p. Exactly the same animation for the other 3 stripes below
  2. The stripes disappear
  3. The cycle repeats

I have a CSS animation code that implements the given scenario:

path{
  stroke-dasharray:10;
  stroke-dashoffset:10;
  fill:none;
  stroke:#000;
}
path:nth-child(1){animation:draw1 4s linear infinite}
path:nth-child(2){animation:draw2 4s linear infinite}
path:nth-child(3){animation:draw3 4s linear infinite}
path:nth-child(4){animation:draw4 4s linear infinite}
@keyframes draw1{
  20%,100%   {stroke-dashoffset:0; }
}
@keyframes draw2{
  20%    {stroke-dashoffset:10;}
  40%,100%   {stroke-dashoffset:0; }
}
@keyframes draw3{
  40%    {stroke-dashoffset:10;}
  60%,100%   {stroke-dashoffset:0; }
}
@keyframes draw4{
  60%    {stroke-dashoffset:10;}
  80%,100%   {stroke-dashoffset:0; }
}
<svg width="220px" height="100px" viewBox="0 0 10 11">
  <path d="M0,1  h10" />
  <path d="M0,4  h10" />
  <path d="M0,7  h10" />
  <path d="M0,10 h10" />  
</svg>

How to execute this animation script using SMIL SVG?

Answer:

Nearby answer by member @ De.Minov completely fulfills the entire scenario mentioned in the question. However, in my opinion, the animation would look a little more interesting if we add a pause between 2 and 3 points of the script. This is how I saw this animation.

Let's execute 1 point of the script:

Given that we are animating simple straight lines, I think it is not at all necessary to use <path> elements for them. I suggest using the <line> elements, defining the necessary coordinates for them, where: x1 is the starting point of the line along the X axis, x2 is the end point of the line along the X axis, and y1 and y2 are the starting and ending points of the line along the Y axis, respectively.

Changing the x1 and x2 coordinates of the line along the X axis we will use in our animation. At the same time, let's complicate the animation a little, slightly deviating from the script:

<svg width="200" height="80">

   <!--Линии-->
   <line id="l1" x1="100" y1="10" x2="100" y2="10" stroke="red" stroke-width="10" />
   <line id="l2" x1="100" y1="30" x2="100" y2="30" stroke="red" stroke-width="10" />
   <line id="l3" x1="100" y1="50" x2="100" y2="50" stroke="red" stroke-width="10" />
   <line id="l4" x1="100" y1="70" x2="100" y2="70" stroke="red" stroke-width="10" />

   <!--Анимация линии 1-->
   <animate href="#l1" attributeName="x1" from="100" to="0" begin="1s" dur="1s" fill="freeze" repeatCount="1"/>
   <animate href="#l1" attributeName="x2" from="100" to="200" begin="1s" dur="1s" fill="freeze" repeatCount="1"/>

   <!--Анимация линии 2-->
   <animate href="#l2" attributeName="x1" from="100" to="0" begin="2s" dur="1s" fill="freeze" repeatCount="1"/>
   <animate href="#l2" attributeName="x2" from="100" to="200" begin="2s" dur="1s" fill="freeze" repeatCount="1"/>

   <!--Анимация линии 3-->
   <animate href="#l3" attributeName="x1" from="100" to="0" begin="3s" dur="1s" fill="freeze" repeatCount="1"/>
   <animate href="#l3" attributeName="x2" from="100" to="200" begin="3s" dur="1s" fill="freeze" repeatCount="1"/>

   <!--Анимация линии 4-->
   <animate href="#l4" attributeName="x1" from="100" to="0" begin="4s" dur="1s" fill="freeze" repeatCount="1"/>
   <animate href="#l4" attributeName="x2" from="100" to="200" begin="4s" dur="1s" fill="freeze" repeatCount="1"/>

</svg>

Let's execute step 2 of the script:

At this point in the script, it is indicated that the lines disappear. But it is not said in what way they disappear, and the time of their disappearance is not indicated. This is unless you take into account the CSS animation code given in the question that implements this scenario. But we will close our eyes to him and pretend that we did not see him 🙂

So, in order to fulfill this point of the script, you can, as an option, apply a property, for example, opacity , which will hide the lines. However, it seemed to me that such an animation would not be entirely interesting. Therefore, we will apply a reverse animation that will return the lines to their original state. At the same time, we will significantly reduce the execution time of such an animation for a better effect.

In the begin attribute, we indicate that the animation will be executed after the execution of the last animation of the appearance of the fourth line ends: begin=an_4_1.end+0.5s , where an_4_1 is the id animation of the increase in the fourth line, and +0.5s is the pause after which the animation will start.

<svg width="200" height="80">

   <!--Линии-->
   <line id="l1" x1="100" y1="10" x2="100" y2="10" stroke="red" stroke-width="10" />
   <line id="l2" x1="100" y1="30" x2="100" y2="30" stroke="red" stroke-width="10" />
   <line id="l3" x1="100" y1="50" x2="100" y2="50" stroke="red" stroke-width="10" />
   <line id="l4" x1="100" y1="70" x2="100" y2="70" stroke="red" stroke-width="10" />

   <!--Анимация увеличения линии 1-->
   <animate id="an_1_1" xlink:href="#l1" attributeName="x1" from="100" to="0" begin="1s" dur="1s" fill="freeze" repeatCount="1"/>
   <animate id="an_1_2" xlink:href="#l1" attributeName="x2" from="100" to="200" begin="1s" dur="1s" fill="freeze" repeatCount="1"/>

   <!--Анимация увеличения линии 2-->
   <animate id="an_2_1" href="#l2" attributeName="x1" from="100" to="0" begin="2s" dur="1s" fill="freeze" repeatCount="1"/>
   <animate id="an_2_2" href="#l2" attributeName="x2" from="100" to="200" begin="2s" dur="1s" fill="freeze" repeatCount="1"/>

   <!--Анимация увеличения линии 3-->
   <animate id="an_3_1" href="#l3" attributeName="x1" from="100" to="0" begin="3s" dur="1s" fill="freeze" repeatCount="1"/>
   <animate id="an_3_2" href="#l3" attributeName="x2" from="100" to="200" begin="3s" dur="1s" fill="freeze" repeatCount="1"/>

   <!--Анимация увеличения линии 4-->
   <animate id="an_4_1" href="#l4" attributeName="x1" from="100" to="0" begin="4s" dur="1s" fill="freeze" repeatCount="1"/>
   <animate id="an_4_2" href="#l4" attributeName="x2" from="100" to="200" begin="4s" dur="1s" fill="freeze" repeatCount="1"/>

   <!--Анимация исчезновения линии 1-->
   <animate xlink:href="#l1" attributeName="x1" from="0" to="100" begin="an_4_1.end+0.5s" dur="0.2s" fill="freeze" repeatCount="1"/>
   <animate xlink:href="#l1" attributeName="x2" from="200" to="100" begin="an_4_2.end+0.5s" dur="0.2s" fill="freeze" repeatCount="1"/>

   <!--Анимация исчезновения линии 2-->
   <animate xlink:href="#l2" attributeName="x1" from="0" to="100" begin="an_4_1.end+0.8s" dur="0.2s" fill="freeze" repeatCount="1"/>
   <animate xlink:href="#l2" attributeName="x2" from="200" to="100" begin="an_4_2.end+0.8s" dur="0.2s" fill="freeze" repeatCount="1"/>

   <!--Анимация исчезновения линии 3-->
   <animate xlink:href="#l3" attributeName="x1" from="0" to="100" begin="an_4_1.end+1.1s" dur="0.2s" fill="freeze" repeatCount="1"/>
   <animate xlink:href="#l3" attributeName="x2" from="200" to="100" begin="an_4_2.end+1.1s" dur="0.2s" fill="freeze" repeatCount="1"/>

   <!--Анимация исчезновения линии 4-->
   <animate xlink:href="#l4" attributeName="x1" from="0" to="100" begin="an_4_1.end+1.4s" dur="0.2s" fill="freeze" repeatCount="1"/>
   <animate xlink:href="#l4" attributeName="x2" from="200" to="100" begin="an_4_2.end+1.4s" dur="0.2s" fill="freeze" repeatCount="1"/>

</svg>

Let's execute 3 point of the script:

In order to execute this point of the script, by analogy with the second point of the script, add a pause in the begin attribute as well: begin=1s;an_1_1.end+5.5s . Only here we will indicate the id not of the previous animation, but of the present one, for example:

<animate id = "an_1_1" begin = "1s; an_1_1 .end + 5.5s" repeatCount = "1" />

At the same time, we must not forget that the indefinite value cannot be set for the repeatCount attribute, otherwise the animation will be infinite and the pause between animation will not work.

<svg width="200" height="80">

   <!--Линии-->
   <line id="l1" x1="100" y1="10" x2="100" y2="10" stroke="red" stroke-width="10" />
   <line id="l2" x1="100" y1="30" x2="100" y2="30" stroke="red" stroke-width="10" />
   <line id="l3" x1="100" y1="50" x2="100" y2="50" stroke="red" stroke-width="10" />
   <line id="l4" x1="100" y1="70" x2="100" y2="70" stroke="red" stroke-width="10" />

   <!--Анимация увеличения линии 1-->
   <animate id="an_1_1" xlink:href="#l1" attributeName="x1" from="100" to="0" begin="1s;an_1_1.end+5.5s" dur="1s" fill="freeze" repeatCount="1"/>
   <animate id="an_1_2" xlink:href="#l1" attributeName="x2" from="100" to="200" begin="1s;an_1_1.end+5.5s" dur="1s" fill="freeze" repeatCount="1"/>

   <!--Анимация увеличения линии 2-->
   <animate id="an_2_1" href="#l2" attributeName="x1" from="100" to="0" begin="2s;an_2_1.end+5.5s" dur="1s" fill="freeze" repeatCount="1"/>
   <animate id="an_2_2" href="#l2" attributeName="x2" from="100" to="200" begin="2s;an_2_2.end+5.5s" dur="1s" fill="freeze" repeatCount="1"/>

   <!--Анимация увеличения линии 3-->
   <animate id="an_3_1" href="#l3" attributeName="x1" from="100" to="0" begin="3s;an_3_1.end+5.5s" dur="1s" fill="freeze" repeatCount="1"/>
   <animate id="an_3_2" href="#l3" attributeName="x2" from="100" to="200" begin="3s;an_3_2.end+5.5s" dur="1s" fill="freeze" repeatCount="1"/>

   <!--Анимация увеличения линии 4-->
   <animate id="an_4_1" href="#l4" attributeName="x1" from="100" to="0" begin="4s;an_4_1.end+5.5s" dur="1s" fill="freeze" repeatCount="1"/>
   <animate id="an_4_2" href="#l4" attributeName="x2" from="100" to="200" begin="4s;an_4_2.end+5.5s" dur="1s" fill="freeze" repeatCount="1"/>

   <!--Анимация уменьшения линии 1-->
   <animate xlink:href="#l1" attributeName="x1" from="0" to="100" begin="an_4_1.end+0.5s" dur="0.2s" fill="freeze" repeatCount="1"/>
   <animate xlink:href="#l1" attributeName="x2" from="200" to="100" begin="an_4_2.end+0.5s" dur="0.2s" fill="freeze" repeatCount="1"/>

   <!--Анимация уменьшения линии 2-->
   <animate xlink:href="#l2" attributeName="x1" from="0" to="100" begin="an_4_1.end+0.8s" dur="0.2s" fill="freeze" repeatCount="1"/>
   <animate xlink:href="#l2" attributeName="x2" from="200" to="100" begin="an_4_2.end+0.8s" dur="0.2s" fill="freeze" repeatCount="1"/>

   <!--Анимация уменьшения линии 3-->
   <animate xlink:href="#l3" attributeName="x1" from="0" to="100" begin="an_4_1.end+1.1s" dur="0.2s" fill="freeze" repeatCount="1"/>
   <animate xlink:href="#l3" attributeName="x2" from="200" to="100" begin="an_4_2.end+1.1s" dur="0.2s" fill="freeze" repeatCount="1"/>

   <!--Анимация уменьшения линии 4-->
   <animate xlink:href="#l4" attributeName="x1" from="0" to="100" begin="an_4_1.end+1.4s" dur="0.2s" fill="freeze" repeatCount="1"/>
   <animate xlink:href="#l4" attributeName="x2" from="200" to="100" begin="an_4_2.end+1.4s" dur="0.2s" fill="freeze" repeatCount="1"/>

</svg>

It turned out so voluminously, I agree. Somewhere something could be shortened, but I do not always aim to make the code shorter. It is always more important for me that it works. Well, something like this)


upd /

The presence of a checkmark (since it so happened that it flew to me), I believe, obliges me to write an answer and complete all the points of the script that are indicated in the question, without deviating from it. So let's do it:

<svg width="200" height="80">

   <!--Линии-->
   <line id="l1" x1="0" y1="10" x2="0" y2="10" stroke="red" stroke-width="10" />
   <line id="l2" x1="0" y1="30" x2="0" y2="30" stroke="red" stroke-width="10" />
   <line id="l3" x1="0" y1="50" x2="0" y2="50" stroke="red" stroke-width="10" />
   <line id="l4" x1="0" y1="70" x2="0" y2="70" stroke="red" stroke-width="10" />

   <!--Анимация появления линий-->
   <animate id="an1" xlink:href="#l1" attributeName="x2" from="0" to="200" begin="1s;an1.end+5.5s" dur="1s" fill="freeze" repeatCount="1"/>
   <animate id="an2" xlink:href="#l2" attributeName="x2" from="0" to="200" begin="2s;an2.end+5.5s" dur="1s" fill="freeze" repeatCount="1"/>
   <animate id="an3" xlink:href="#l3" attributeName="x2" from="0" to="200" begin="3s;an3.end+5.5s" dur="1s" fill="freeze" repeatCount="1"/>
   <animate id="an4" xlink:href="#l4" attributeName="x2" from="0" to="200" begin="4s;an4.end+5.5s" dur="1s" fill="freeze" repeatCount="1"/>

   <!--Анимация исчезновения линий-->
   <animate id="op1" xlink:href="#l1" attributeName="x2" from="200" to="0" begin="an4.end+0.8s" dur="0.001s" fill="freeze" repeatCount="1"/>
   <animate id="op2" xlink:href="#l2" attributeName="x2" from="200" to="0" begin="an4.end+0.8s" dur="0.001s" fill="freeze" repeatCount="1"/>
   <animate id="op3" xlink:href="#l3" attributeName="x2" from="200" to="0" begin="an4.end+0.8s" dur="0.001s" fill="freeze" repeatCount="1"/>
   <animate id="op4" xlink:href="#l4" attributeName="x2" from="200" to="0" begin="an4.end+0.8s" dur="0.001s" fill="freeze" repeatCount="1"/>

</svg>

Here we also apply reverse animation to each element separately. Only the animation execution time dur="0.001s" is set as little as possible, so that the lines disappear almost immediately. And of course, we add pauses between all points in the script to make it look proportionally interesting.

It is a pity that you cannot apply a batch change of coordinates to all elements at once. If there was such a possibility, then we could wrap all the elements in a separate tag:

   <g id="lines">
   элементы
   </g>

and write just one animation, for example:

<animate xlink:href="#lines" attributeName="x2" from="200" to="0" .../>

However, unfortunately, there is no such possibility.

Scroll to Top