1

Мне нужно, чтобы плавно прорисовывалась иконка бесконечности. Не особо разбираюсь в svg, поэтому просто нагуглил решение с stroke-dashoffset. Но проблема в том, что я хочу, чтобы вместе с контуром прорисовывалась внутренняя область иконки. Думал, что stroke-width в этом поможет, а нет - stroke, оказывается, только наружу утолщается. Буду благодарен, если поможете решить этот вопрос.введите сюда описание изображения

.infinity path {
  animation: paint 2s ease-in-out infinite normal forwards;
}

@keyframes paint { from { stroke-dashoffset: 1900; } to { stroke-dashoffset: 0; } }

<svg class="infinity" width="401" height="211" viewBox="0 0 401 211" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path fill-rule="evenodd" clip-rule="evenodd"
            d="M160.757 13.8069C182.986 25.1339 182.889 24.7064 169.22 51.0624C157.286 74.0816 154.036 75.0192 135.236 60.8382C116.554 46.7467 94.9468 48.2083 73.5333 65.0091C47.7984 85.1879 47.7984 126.552 73.5333 146.731C111.43 176.458 134.095 164.345 177.565 91.1513C199.138 54.8265 220.15 28.8911 237.166 17.5987C306.35 -28.3019 401.069 22.3211 401 105.167C400.952 165.835 356.749 209.205 294.921 209.253C263.123 209.281 221.257 192.639 221.257 179.974C221.257 175.431 236.44 148.165 246.895 133.95C248.084 132.329 252.917 136.169 257.626 142.477C272.968 163.001 306.392 164.435 328.455 145.518C355.034 122.719 355.352 89.2968 329.195 66.8635C290.634 33.7859 264.637 47.6222 219.355 125.325C181.776 189.805 152.909 211.687 106.314 210.984C47.4458 210.094 0 164.118 0 107.952C0 23.3759 83.5244 -25.5443 160.757 13.8069Z"
            stroke="#393939" stroke-dasharray="1900" stroke-dashoffset="1900"/>
    </svg>
Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384

2 Answers2

2

Нужно нарисовать иконку бесконечности одиночным контуром (линией). И в этом случае можно задать толщину линии, например: stroke-width="10".

сравните:
stroke-width="1"

body {background:white;}
.container 
{
 width:50vw;
 height:50vh;

} #infinity { fill:none; stroke:black; stroke-width:1;

<div class="container"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 25 100 100">

<path id="infinity" fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="#d3d3d3" stroke-width="10" />
</svg> </div>

<div class="container">
<svg xmlns="http://www.w3.org/2000/svg"  viewBox="0 25 100 100">

  <path id="infinity" fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="#d3d3d3" stroke-width="10"  />  
 </svg>
</div>

stroke-width="10"

let path = document.querySelector("#infinity");
let length = path.getTotalLength();
console.log(length);
body {background:white;}
.container 
{
 width:50vw;
 height:50vh;

} #infinity { fill:none; stroke:black; stroke-width:10;

<div class="container">
<svg xmlns="http://www.w3.org/2000/svg"  viewBox="0 25 100 100">

  <path id="infinity" fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="#d3d3d3" stroke-width="10"  />  
 </svg>
</div>

Обратите внимание, в примере выше с помощью getTotalLength() вычислена общая длина
линии =~ 256.6px. Анимация рисования линии реализуется с помощью уменьшения
stroke-dashoffset - отступа от начала линии, от максимума 256.6 до нуля

.container 
{
 width:50vw;
 height:50vh;

} #infinity { fill:none; stroke:black; stroke-width:10; stroke-dashoffset:256.6; stroke-dasharray:256.6; animation: paint 2s ease-in-out infinite normal forwards; }

@keyframes paint { from { stroke-dashoffset: 256.6; } to { stroke-dashoffset: 0; } }

<div class="container">
<svg xmlns="http://www.w3.org/2000/svg"  viewBox="0 25 100 100">

  <path id="infinity" fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="#d3d3d3" stroke-width="10"  />  
 </svg>
</div>
Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384
2

Другие примеры анимации иконки бесконечности при помощи stroke-dasharray

Анимация симметричного заполнения иконки из одной точки

Подробно рассказано об этой оригинальной технике здесь. Смотрите вторую половину ответа.

Максимальная длина линии =~ 257px. Половина - 128.5px Четверть пути - 64.2px. Эти цифры понадобятся для сдвига начала path командой stroke-dashoffset="128.5"

Пример заполнения фигуры из середины path

Обратите внимание, что фигура одновременно, симметрично заполняется из центра, пока края не сомкнутся.

body {background:#2F2F2F;}
.container 
{
 width:35%;
 height:35%;

}

<div class="container">
<svg xmlns="http://www.w3.org/2000/svg"  viewBox="0 20 100 100">

  <path fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="#d3d3d3" stroke-width="10"  />  

    <path id="path1" fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="greenyellow" stroke-width="10" stroke-dashoffset="31.1" stroke-dasharray="0 128.5" >  
      <animate
        xlink:href="#path1"
        attributeName="stroke-dasharray"
        values="0 128.5 0 128.5;0 0 257 0"
        begin="btn.click"
        dur="4s"
        fill="freeze"/> 
    </path> 

    <g id="btn" transform="translate(12 0)">
      <rect x="20" y="84" width="35" height="15" rx="5" fill="none" stroke="dodgerblue"/>
         <text x="24" y="94" font-size="10" fill="crimson" >Центр</text>
    </g>
</svg>
</div>

Комплексный пример заполнения

Начать заполнение можно из любой точки фигуры, для этого надо сдвинуть начало рисования линии от начала с помощью изменения числового значения атрибута stroke-dashoffset

В приложении кнопка L, - запускает рисование с левого края

R - справа (right)

T - сверху (top)

C - центр (center)

B - снизу (bottom)

На эти обозначения ориентируйтесь при разборе кода id="btn_c", <path id="center"

.container
{
width:30%;
height:30%;  
 background:black;
}
<div class="container">
<svg xmlns="http://www.w3.org/2000/svg"  viewBox="0 25 100 100">

<path fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="#d3d3d3" stroke-width="10" />
<!-- Средняя точка начала анимации в центре слева stroke-dashoffset="31.1" --> <path id="center" fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="crimson" stroke-width="10" stroke-dashoffset="31.1" stroke-dasharray="0 128.5" >
<animate attributeName="stroke-dasharray" values="0 128.5 0 128.5;0 0 257 0" begin="btn_C.click" dur="4s" restart="whenNotActive" /> </path> <!-- Средняя точка слева stroke-dashoffset="-159.5" --> <path id="Left" fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="yellowgreen" stroke-width="10" stroke-dashoffset="-159.5" stroke-dasharray="0 128.5" >
<animate attributeName="stroke-dasharray" values="0 128.5 0 128.5;0 0 257 0" begin="btn_L.click" dur="4s" restart="whenNotActive" /> </path>

   &lt;!-- Средняя точка слева сверху stroke-dashoffset="128.5" --&gt;
    &lt;path id="Top" fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="gold" stroke-width="10" stroke-dashoffset="128.5" stroke-dasharray="0 128.5" &gt;  
  &lt;animate
    attributeName="stroke-dasharray"
    values="0 128.5 0 128.5;0 0 257 0"
    begin="btn_T.click"
    dur="4s"
    restart="whenNotActive" /&gt; 
&lt;/path&gt; 
    &lt;!-- Средняя точка справа внизу  stroke-dashoffset="192.7" --&gt;
 &lt;path id="Bottom" fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="dodgerblue" stroke-width="10" stroke-dashoffset="192.7" stroke-dasharray="0 128.5" &gt;  
  &lt;animate
    attributeName="stroke-dasharray"
    values="0 128.5 0 128.5;0 0 257 0"
    begin="btn_B.click"
    dur="4s"
    restart="whenNotActive" /&gt; 
&lt;/path&gt;   

       &lt;!-- Средняя точка справа   stroke-dashoffset="223.9" --&gt;
 &lt;path id="Bottom" fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="purple" stroke-width="10" stroke-dashoffset="223.9" stroke-dasharray="0 128.5" &gt;  
  &lt;animate
    attributeName="stroke-dasharray"
    values="0 128.5 0 128.5;0 0 257 0"
    begin="btn_R.click"
    dur="4s"
    restart="whenNotActive" /&gt; 
&lt;/path&gt; 



<g id="btn_L" transform="translate(-17 0)" > <rect x="20" y="84" width="15" height="15" rx="7.5" fill="none" stroke="#B2B2B2"/> <text x="25" y="95" font-size="10" fill="green" >L</text> </g>
<g id="btn_C" transform="translate(3 0)"> <rect x="20" y="84" width="15" height="15" rx="7.5" fill="none" stroke="#B2B2B2"/> <text x="24" y="95" font-size="10" fill="crimson" >C</text> </g>

    &lt;g id="btn_T" transform="translate(23 0)" &gt;
  &lt;rect x="20" y="84" width="15" height="15" rx="7.5" fill="none" stroke="dodgerblue"/&gt;
     &lt;text x="24" y="95" font-size="10" fill="orange" &gt;T&lt;/text&gt;
    &lt;/g&gt;  

<g id="btn_B" transform="translate(43 0)"> <rect x="20" y="84" width="15" height="15" rx="7.5" fill="none" stroke="#B2B2B2"/> <text x="25" y="95" font-size="10" fill="dodgerblue" >B</text> </g>
<g id="btn_R" transform="translate(63 0)"> <rect x="20" y="84" width="15" height="15" rx="7.5" fill="none" stroke="#B2B2B2"/> <text x="25" y="95" font-size="10" fill="purple" >R</text> </g>
</svg> </div>

Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384