Создаем glitch-эффект как в Cyberpunk 2077 для изображения с помощью CSS

от автора

Photo by Hyunwon Jang on Unsplash
Photo by Hyunwon Jang on Unsplash

Зайдя на сайт Cyberpunk 2077 в раздел новостей, я наткнулся на «тот самый» эффект. Он появлялся при наведении на изображение поста. Мне показалось это интересным и я решил посмотреть как это работает. В этом посте я хотел бы поделиться тем, что нарыл.

Для достижения этого эффекта, нам необходимо 2 раза вывести изображение, наложив их друг на друга. Сам эффект будет проявляться на изображении, которое лежит сверху.

Итак, создаем контейнер с двумя изображениями. Сами изображения будут добавлены как фон.

<div class="container">   <div class="img"></div>   <div class="glitch"></div> </div>

Прописываем общие стили для дочерних элементов.

.img, .glitch {   display: block;   background-image: url('https://images.unsplash.com/photo-1551771685-c367c9127a03?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80');   background-repeat: no-repeat;   background-size: cover;   width: 564px;   height: 376px; }

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

.glitch {   position: absolute;   top: 0;   left: 0;   right: 0;   bottom: 0; } .container {   position: relative; }

Отлично. Теперь самое интересное. Мы добавим анимацию при наведении на изображение.

.glitch:hover {  -webkit-animation-duration:2s;  animation-duration:2s;  -webkit-animation-timing-function:linear;  animation-timing-function:linear;  -webkit-animation-iteration-count:infinite;  animation-iteration-count:infinite;  -webkit-animation-name:glitch-anim;  animation-name:glitch-anim;  -webkit-animation-direction:alternate;  animation-direction:alternate }

Рассмотрим подробнее каждое свойство:

  • animation-duration — продолжительность анимации, 2 секунды;

  • animation-timing-function — используем линейную функцию, чтобы анимация происходила равномерно;

  • animation-iteration-count — повторяем анимацию бесконечно;

  • animation-name — идентификатор анимации, ее мы опишем чуть ниже;

  • animation-direction — направление анимации, при значении alternate анимация идет с начала до конца, а потом обратно.

Осталась последняя деталь — описать саму анимацию. Для этого воспользуемся правилом @keyframes.

Spoiler
@keyframes glitch-anim {  0% {   opacity:1;   -webkit-transform:translateZ(0);   transform:translateZ(0);   -webkit-clip-path:polygon(0 2%,100% 2%,100% 5%,0 5%);   clip-path:polygon(0 2%,100% 2%,100% 5%,0 5%)  }  2% {   -webkit-clip-path:polygon(0 78%,100% 78%,100% 100%,0 100%);   clip-path:polygon(0 78%,100% 78%,100% 100%,0 100%);   -webkit-transform:translate(-5px);   transform:translate(-5px)  }  6% {   -webkit-clip-path:polygon(0 78%,100% 78%,100% 100%,0 100%);   clip-path:polygon(0 78%,100% 78%,100% 100%,0 100%);   -webkit-transform:translate(5px);   transform:translate(5px)  }  8% {   -webkit-clip-path:polygon(0 78%,100% 78%,100% 100%,0 100%);   clip-path:polygon(0 78%,100% 78%,100% 100%,0 100%);   -webkit-transform:translate(-5px);   transform:translate(-5px)  }  9% {   -webkit-clip-path:polygon(0 78%,100% 78%,100% 100%,0 100%);   clip-path:polygon(0 78%,100% 78%,100% 100%,0 100%);   -webkit-transform:translate(0);   transform:translate(0)  }  10% {   -webkit-clip-path:polygon(0 54%,100% 54%,100% 44%,0 44%);   clip-path:polygon(0 54%,100% 54%,100% 44%,0 44%);   -webkit-transform:translate3d(5px,0,0);   transform:translate3d(5px,0,0)  }  13% {   -webkit-clip-path:polygon(0 54%,100% 54%,100% 44%,0 44%);   clip-path:polygon(0 54%,100% 54%,100% 44%,0 44%);   -webkit-transform:translateZ(0);   transform:translateZ(0)  }  13.1% {   -webkit-clip-path:polygon(0 0,0 0,0 0,0 0);   clip-path:polygon(0 0,0 0,0 0,0 0);   -webkit-transform:translate3d(5px,0,0);   transform:translate3d(5px,0,0)  }  15% {   -webkit-clip-path:polygon(0 60%,100% 60%,100% 40%,0 40%);   clip-path:polygon(0 60%,100% 60%,100% 40%,0 40%);   -webkit-transform:translate3d(5px,0,0);   transform:translate3d(5px,0,0)  }  20% {   -webkit-clip-path:polygon(0 60%,100% 60%,100% 40%,0 40%);   clip-path:polygon(0 60%,100% 60%,100% 40%,0 40%);   -webkit-transform:translate3d(-5px,0,0);   transform:translate3d(-5px,0,0)  }  20.1% {   -webkit-clip-path:polygon(0 0,0 0,0 0,0 0);   clip-path:polygon(0 0,0 0,0 0,0 0);   -webkit-transform:translate3d(5px,0,0);   transform:translate3d(5px,0,0)  }  25% {   -webkit-clip-path:polygon(0 85%,100% 85%,100% 40%,0 40%);   clip-path:polygon(0 85%,100% 85%,100% 40%,0 40%);   -webkit-transform:translate3d(5px,0,0);   transform:translate3d(5px,0,0)  }  30% {   -webkit-clip-path:polygon(0 85%,100% 85%,100% 40%,0 40%);   clip-path:polygon(0 85%,100% 85%,100% 40%,0 40%);   -webkit-transform:translate3d(-5px,0,0);   transform:translate3d(-5px,0,0)  }  30.1% {   -webkit-clip-path:polygon(0 0,0 0,0 0,0 0);   clip-path:polygon(0 0,0 0,0 0,0 0)  }  35% {   -webkit-clip-path:polygon(0 63%,100% 63%,100% 80%,0 80%);   clip-path:polygon(0 63%,100% 63%,100% 80%,0 80%);   -webkit-transform:translate(-5px);   transform:translate(-5px)  }  40% {   -webkit-clip-path:polygon(0 63%,100% 63%,100% 80%,0 80%);   clip-path:polygon(0 63%,100% 63%,100% 80%,0 80%);   -webkit-transform:translate(5px);   transform:translate(5px)  }  45% {   -webkit-clip-path:polygon(0 63%,100% 63%,100% 80%,0 80%);   clip-path:polygon(0 63%,100% 63%,100% 80%,0 80%);   -webkit-transform:translate(-5px);   transform:translate(-5px)  }  50% {   -webkit-clip-path:polygon(0 63%,100% 63%,100% 80%,0 80%);   clip-path:polygon(0 63%,100% 63%,100% 80%,0 80%);   -webkit-transform:translate(0);   transform:translate(0)  }  55% {   -webkit-clip-path:polygon(0 10%,100% 10%,100% 0,0 0);   clip-path:polygon(0 10%,100% 10%,100% 0,0 0);   -webkit-transform:translate3d(5px,0,0);   transform:translate3d(5px,0,0)  }  60% {   -webkit-clip-path:polygon(0 10%,100% 10%,100% 0,0 0);   clip-path:polygon(0 10%,100% 10%,100% 0,0 0);   -webkit-transform:translateZ(0);   transform:translateZ(0);   opacity:1  }  60.1% {   -webkit-clip-path:polygon(0 0,0 0,0 0,0 0);   clip-path:polygon(0 0,0 0,0 0,0 0);   opacity:1  }  to {   -webkit-clip-path:polygon(0 0,0 0,0 0,0 0);   clip-path:polygon(0 0,0 0,0 0,0 0);   opacity:1  } }

Пояснения к коду.

Анимация разбита на части в процентном соотношении. В каждой части происходят определенные изменения.

С помощью свойства clip-path вырезается полигон из изображения и к нему применяются различные эффекты. Например, transform: translate(-5px) — сдвигает полигон влево и вверх.

Посмотреть что получилось можно по ссылке.

ссылка на оригинал статьи https://habr.com/ru/post/533252/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *