pagetop

BLOG

【js】イメージにグリッチエフェクト効果を実装する

  • HOME

  • BLOG

  • 【js】イメージにグリッチエフェクト効果を実装する

Article

【js】イメージにグリッチエフェクト効果を実装する

【js】イメージにグリッチエフェクト効果を実装する

グリッチエフェクトを使ってイメージにノイズ効果を実装するjsをメモします。

 

グリッチエフェクトとは

グリッチとは故障を意味し、ゲーム・動画等のバグが起こった際の画面のノイズことを指します。このノイズを反映した効果を「グリッチエフェクト」と言います。
ホラー映画などで見る機会が多く、WEB、グラフィックデザインにも多く使用されています。

 

実装してみる

グリッチエフェクト

上記のイメージのようなエフェクトを実装したいと思います。

 

html

<main class="demo-1">
<div class="content">
<div class="glitch">
<div class="glitch__img"></div>
<div class="glitch__img"></div>
<div class="glitch__img"></div>
<div class="glitch__img"></div>
<div class="glitch__img"></div>
</div>

</div>
</main>
<script src="js/imagesloaded.pkgd.min.js"></script>
<script src="js/function.js"></script>

ポイントはglitch__imgセレクタです。cssで定義しますが、glitch__imgには背景イメージを設定します。
上記では同じ背景イメージ複数設定しています。それをnth-childを使用しkeyframesにより異なるアニメーションを設定します。

 

js

プラグインには、お馴染みのimagesloaded.pkgd.min.jsを実装します。function.jsに機能を記述します。

{
imagesLoaded('.glitch__img', { background: true }, () => {
document.body.classList.add('imgloaded');
});
}

 

css

.demo-1 {
--glitch-width: 100vw;
--glitch-height: 100vh;
--gap-horizontal: 10px;
--gap-vertical: 5px;
--time-anim: 4s;
--delay-anim: 2s;
}

.glitch {
position: absolute;
top: 0;
left: 0;
width: var(--glitch-width);
height: var(--glitch-height);
overflow: hidden;
}

.glitch__img {
position: absolute;
top: calc(-1 * var(--gap-vertical));
left: calc(-1 * var(--gap-horizontal));
width: calc(100% + var(--gap-horizontal) * 2);
height: calc(100% + var(--gap-vertical) * 2);
background: url(../img/1.jpg) no-repeat 50% 0;
background-color: var(--blend-color-1);
background-size: cover;
transform: translate3d(0,0,0);
background-blend-mode: var(--blend-mode-1);
}

.glitch__img:nth-child(n+2) {
opacity: 0;
}

.imgloaded .glitch__img:nth-child(n+2) {
animation-duration: var(--time-anim);
animation-delay: var(--delay-anim);
animation-timing-function: linear;
animation-iteration-count: infinite;
}

.imgloaded .glitch__img:nth-child(2) {
background-color: var(--blend-color-2);
background-blend-mode: var(--blend-mode-2);
animation-name: glitch-anim-1;
}

.imgloaded .glitch__img:nth-child(3) {
background-color: var(--blend-color-3);
background-blend-mode: var(--blend-mode-3);
animation-name: glitch-anim-2;
}

.imgloaded .glitch__img:nth-child(4) {
background-color: var(--blend-color-4);
background-blend-mode: var(--blend-mode-4);
animation-name: glitch-anim-3;
}

.imgloaded .glitch__img:nth-child(5) {
background-color: var(--blend-color-5);
background-blend-mode: var(--blend-mode-5);
animation-name: glitch-anim-flash;
}


@keyframes glitch-anim-1 {
0% { 
opacity: 1;
transform: translate3d(var(--gap-horizontal),0,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 15%, 100% 15%, 100% 15%, 0 15%);
clip-path: polygon(0 15%, 100% 15%, 100% 15%, 0 15%);
}
4% {
-webkit-clip-path: polygon(0 10%, 100% 10%, 100% 20%, 0 20%);
clip-path: polygon(0 10%, 100% 10%, 100% 20%, 0 20%);
}
6% {
-webkit-clip-path: polygon(0 1%, 100% 1%, 100% 2%, 0 2%);
clip-path: polygon(0 1%, 100% 1%, 100% 2%, 0 2%);
}
8% {
-webkit-clip-path: polygon(0 33%, 100% 33%, 100% 33%, 0 33%);
clip-path: polygon(0 33%, 100% 33%, 100% 33%, 0 33%);
}
10% {
-webkit-clip-path: polygon(0 44%, 100% 44%, 100% 44%, 0 44%);
clip-path: polygon(0 44%, 100% 44%, 100% 44%, 0 44%);
}
12% {
-webkit-clip-path: polygon(0 50%, 100% 50%, 100% 20%, 0 20%);
clip-path: polygon(0 50%, 100% 50%, 100% 20%, 0 20%);
}
14% {
-webkit-clip-path: polygon(0 70%, 100% 70%, 100% 70%, 0 70%);
clip-path: polygon(0 70%, 100% 70%, 100% 70%, 0 70%);
}
16% {
-webkit-clip-path: polygon(0 80%, 100% 80%, 100% 80%, 0 80%);
clip-path: polygon(0 80%, 100% 80%, 100% 80%, 0 80%);
}
18% {
-webkit-clip-path: polygon(0 50%, 100% 50%, 100% 55%, 0 55%);
clip-path: polygon(0 50%, 100% 50%, 100% 55%, 0 55%);
}
20% {
-webkit-clip-path: polygon(0 70%, 100% 70%, 100% 80%, 0 80%);
clip-path: polygon(0 70%, 100% 70%, 100% 80%, 0 80%);
}
21.9% {
opacity: 1;
transform: translate3d(var(--gap-horizontal),0,0);
}
22%, 100% {
opacity: 0;
transform: translate3d(0,0,0);
-webkit-clip-path: polygon(0 0, 0 0, 0 0, 0 0);
clip-path: polygon(0 0, 0 0, 0 0, 0 0);
}
}

@keyframes glitch-anim-2 {
0% { 
opacity: 1;
transform: translate3d(calc(-1 * var(--gap-horizontal)),0,0);
-webkit-clip-path: polygon(0 25%, 100% 25%, 100% 30%, 0 30%);
clip-path: polygon(0 25%, 100% 25%, 100% 30%, 0 30%);
}
3% {
-webkit-clip-path: polygon(0 3%, 100% 3%, 100% 3%, 0 3%);
clip-path: polygon(0 3%, 100% 3%, 100% 3%, 0 3%);
}
5% {
-webkit-clip-path: polygon(0 5%, 100% 5%, 100% 20%, 0 20%);
clip-path: polygon(0 5%, 100% 5%, 100% 20%, 0 20%);
}
7% {
-webkit-clip-path: polygon(0 20%, 100% 20%, 100% 20%, 0 20%);
clip-path: polygon(0 20%, 100% 20%, 100% 20%, 0 20%);
}
9% {
-webkit-clip-path: polygon(0 40%, 100% 40%, 100% 40%, 0 40%);
clip-path: polygon(0 40%, 100% 40%, 100% 40%, 0 40%);
}
11% {
-webkit-clip-path: polygon(0 52%, 100% 52%, 100% 59%, 0 59%);
clip-path: polygon(0 52%, 100% 52%, 100% 59%, 0 59%);
}
13% {
-webkit-clip-path: polygon(0 60%, 100% 60%, 100% 60%, 0 60%);
clip-path: polygon(0 60%, 100% 60%, 100% 60%, 0 60%);
}
15% {
-webkit-clip-path: polygon(0 75%, 100% 75%, 100% 75%, 0 75%);
clip-path: polygon(0 75%, 100% 75%, 100% 75%, 0 75%);
}
17% {
-webkit-clip-path: polygon(0 65%, 100% 65%, 100% 40%, 0 40%);
clip-path: polygon(0 65%, 100% 65%, 100% 40%, 0 40%);
}
19% {
-webkit-clip-path: polygon(0 45%, 100% 45%, 100% 50%, 0 50%);
clip-path: polygon(0 45%, 100% 45%, 100% 50%, 0 50%);
}
20% {
-webkit-clip-path: polygon(0 14%, 100% 14%, 100% 33%, 0 33%);
clip-path: polygon(0 14%, 100% 14%, 100% 33%, 0 33%);
}
21.9% {
opacity: 1;
transform: translate3d(calc(-1 * var(--gap-horizontal)),0,0);
}
22%, 100% {
opacity: 0;
transform: translate3d(0,0,0);
-webkit-clip-path: polygon(0 0, 0 0, 0 0, 0 0);
clip-path: polygon(0 0, 0 0, 0 0, 0 0);
}
}

@keyframes glitch-anim-3 {
0% { 
opacity: 1;
transform: translate3d(0, calc(-1 * var(--gap-vertical)), 0) scale3d(-1,-1,1);
-webkit-clip-path: polygon(0 1%, 100% 1%, 100% 3%, 0 3%);
clip-path: polygon(0 1%, 100% 1%, 100% 3%, 0 3%);
}
1.5% {
-webkit-clip-path: polygon(0 10%, 100% 10%, 100% 9%, 0 9%);
clip-path: polygon(0 10%, 100% 10%, 100% 9%, 0 9%);
}
2% {
-webkit-clip-path: polygon(0 5%, 100% 5%, 100% 6%, 0 6%);
clip-path: polygon(0 5%, 100% 5%, 100% 6%, 0 6%);
}
2.5% {
-webkit-clip-path: polygon(0 20%, 100% 20%, 100% 20%, 0 20%);
clip-path: polygon(0 20%, 100% 20%, 100% 20%, 0 20%);
}
3% {
-webkit-clip-path: polygon(0 10%, 100% 10%, 100% 10%, 0 10%);
clip-path: polygon(0 10%, 100% 10%, 100% 10%, 0 10%);
}
5% {
-webkit-clip-path: polygon(0 30%, 100% 30%, 100% 25%, 0 25%);
clip-path: polygon(0 30%, 100% 30%, 100% 25%, 0 25%);
}
5.5% {
-webkit-clip-path: polygon(0 15%, 100% 15%, 100% 16%, 0 16%);
clip-path: polygon(0 15%, 100% 15%, 100% 16%, 0 16%);
}
7% {
-webkit-clip-path: polygon(0 40%, 100% 40%, 100% 39%, 0 39%);
clip-path: polygon(0 40%, 100% 40%, 100% 39%, 0 39%);
}
8% {
-webkit-clip-path: polygon(0 20%, 100% 20%, 100% 21%, 0 21%);
clip-path: polygon(0 20%, 100% 20%, 100% 21%, 0 21%);
}
9% {
-webkit-clip-path: polygon(0 60%, 100% 60%, 100% 55%, 0 55%);
clip-path: polygon(0 60%, 100% 60%, 100% 55%, 0 55%);
}
10.5% {
-webkit-clip-path: polygon(0 30%, 100% 30%, 100% 31%, 0 31%);
clip-path: polygon(0 30%, 100% 30%, 100% 31%, 0 31%);
}
11% {
-webkit-clip-path: polygon(0 70%, 100% 70%, 100% 69%, 0 69%);
clip-path: polygon(0 70%, 100% 70%, 100% 69%, 0 69%);
}
13% {
-webkit-clip-path: polygon(0 40%, 100% 40%, 100% 41%, 0 41%);
clip-path: polygon(0 40%, 100% 40%, 100% 41%, 0 41%);
}
14% {
-webkit-clip-path: polygon(0 80%, 100% 80%, 100% 75%, 0 75%);
clip-path: polygon(0 80%, 100% 80%, 100% 75%, 0 75%);
}
14.5% {
-webkit-clip-path: polygon(0 50%, 100% 50%, 100% 51%, 0 51%);
clip-path: polygon(0 50%, 100% 50%, 100% 51%, 0 51%);
}
15% {
-webkit-clip-path: polygon(0 90%, 100% 90%, 100% 90%, 0 90%);
clip-path: polygon(0 90%, 100% 90%, 100% 90%, 0 90%);
}
16% {
-webkit-clip-path: polygon(0 60%, 100% 60%, 100% 60%, 0 60%);
clip-path: polygon(0 60%, 100% 60%, 100% 60%, 0 60%);
}
18% {
-webkit-clip-path: polygon(0 100%, 100% 100%, 100% 99%, 0 99%);
clip-path: polygon(0 100%, 100% 100%, 100% 99%, 0 99%);
}
20% {
-webkit-clip-path: polygon(0 70%, 100% 70%, 100% 71%, 0 71%);
clip-path: polygon(0 70%, 100% 70%, 100% 71%, 0 71%);
}
21.9% {
opacity: 1;
transform: translate3d(0, calc(-1 * var(--gap-vertical)), 0) scale3d(-1,-1,1);
}
22%, 100% {
opacity: 0;
transform: translate3d(0,0,0);
-webkit-clip-path: polygon(0 0, 0 0, 0 0, 0 0);
clip-path: polygon(0 0, 0 0, 0 0, 0 0);
}
}

@keyframes glitch-anim-flash { {
0%, 5% { 
opacity: 0.2; 
transform: translate3d(var(--gap-horizontal), var(--gap-vertical), 0);
}
5.5%, 100% {
opacity: 0;
transform: translate3d(0, 0, 0);
}
}

 

以上です。

比較的簡単に実装できますね。
用途はある程度限定されるでしょうが、有効的に使用したいと思います。

デモはこちら

Spread the love