10

введите сюда описание изображения

Можно ли с помощью CSS сделать такую анимацию, чтобы некую выпуклость превратить в вогнутость ? Если да, то с помощью чего ?

Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384
Bim Bam
  • 922

2 Answers2

12

Решение SVG

Реализовать кривую такой формы проще всего с помощью Кривых Безье второго порядка.

введите сюда описание изображения

Из рисунка выше видно, что можно получить последовательные кадры анимации, как у автора вопроса. Для этого надо изменять у параметра Q координаты x1 и y1

Итак пишем несколько формул для нескольких патчей, составленных из квадратичных кривых Безье. Теория здесь.

<svg xmlns:xlink="http://www.w3.org/1999/xlink" 
    xmlns="http://www.w3.org/2000/svg"
 version="1.1" width="300px" height="300px" viewBox="50 -50 300 300" style="border:1px solid red;" >

<path d="M100,100 Q204,200 297,100" style="stroke:blue; stroke-width:3; fill:none;" />

<path d="M100,100 Q204,167 297,100" style="stroke:blue; stroke-width:3; fill:none;" />

<path d="M100,100 Q204,100 297,100" style="stroke:blue; stroke-width:3; fill:none;" />

<path d="M100,100 Q204,50 297,100" style="stroke:blue; stroke-width:3; fill:none;" />

<path d="M100,100 Q204,20 297,100" style="stroke:blue; stroke-width:3; fill:none;" />

<circle cx="100" cy="100" r="6" style="fill:none; stroke:orangered; stroke-width:3px;" /> <circle cx="297" cy="100" r="6" style="fill:none; stroke:orangered; stroke-width:3px;" />

</svg>

Для написания формул кривых Безье есть - онлайн генератор

На втором этапе делаем анимацию движения кривой, путем последовательного перебора всех кривых Безье.

<svg xmlns:xlink="http://www.w3.org/1999/xlink" 
    xmlns="http://www.w3.org/2000/svg"
 version="1.1" width="350px" height="300px" viewBox="0 50 300 350">
    <defs>
    <linearGradient id="LinGrad"
                    x1="0%" y1="0%"
                    x2="0%" y2="100%"
                    spreadMethod="pad">
      <stop offset="0%"   stop-color="dodgerblue" stop-opacity="1"/>
      <stop offset="75%" stop-color="white" stop-opacity="1"/>
   <stop offset="25%" stop-color="green" stop-opacity="1"/>
    </linearGradient>
  </defs>

<rect x="10" y="10" width="350" height="350" rx="10" ry="10" transform="translate(50 0)" style="fill:url(#LinGrad); opacity:0.5;" />

<path d="M100,100 Q204,200 297,100" style="stroke:dodgerblue; stroke-width:3; fill:none;" >

&lt;animate
  attributeName="d"
  dur="2s"
  repeatCount="3"
  values=
   "M100,100 Q204,200 297,100;
    M100,100 Q204,167 297,100;
    M100,100 Q204,100 297,100;
    M100,100 Q204,50 297,100;
    M100,100 Q204,20 297,100"/&gt; 
&lt;/path&gt;

<circle cx="100" cy="100" r="6" style="fill:none; stroke:orangered; stroke-width:3px;" /> <circle cx="297" cy="100" r="6" style="fill:none; stroke:orangered; stroke-width:3px;" />
</svg>

Анимацию осуществляет команда

animate attributeName="d" dur="2s" repeatCount="3"

в параметр values="M100,100 Q204,200 297,100;M100,100 Q204,167 297,100;

добавлены через точку с запятой все промежуточные положения квадратичной кривой Безье.

Ещё один пример анимации квадратичных кривых Безье.

Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384
5

Благодаря анимации CSS свойства transform.

div {
  border-radius: 50%;
  width: 100px;
  height: 100px;
  border-bottom: 2px solid black;
  animation-name: animation;
  animation-duration: 2s;
}

@keyframes animation { from { transform: none; } to { transform: rotateX(180deg); } }

<div>
</div>

C помощью двух блоков, CSS-анимаций и игрой с border-radius.

div {
  border-radius: 50%;
  width: 100px;
  height: 100px;
}
#top {
  animation-name: top;
  animation-duration: 2s;
}
#bottom {
  animation-name: bottom;
  animation-duration: 2s;
  animation-delay: 2s;
}
@keyframes top {
  from {
    border-radius: 50%;
    border-bottom: 1px solid black;
    height: 100px;
  }
  to {
    border-radius: 0%;
    border-bottom: 1px solid black;
    height: 50px;
  }
}
@keyframes bottom {
  from {
    border-radius: 0%;
    border-top: 1px solid black;
    margin-top: -50px;
  }
  to {
    border-radius: 25%;
    border-top: 1px solid black;
    margin-top: -75px;
  }
  100% {
    border-radius: 50%;
    border-top: 1px solid black;
    margin-top: -100px;
  }
}
<div id="top">
</div>

<div id="bottom"> </div>