개발 기술/css 애니메이션 (with js)

이미지 로딩 애니메이션(feat. 저화질, skeleton loading)

by GicoMomg 2021. 9. 23.

이미지를 로딩하는 동안, 그 공백을 채우는 방법은 여러가지가 있다.
이번 시간에는 저화질의 이미지 혹은 skeleton 로딩을 띄우는 방법을 알아보자!


1. 저화질 이미지 먼저 띄우기

A. 원본의 저화질 이미지 준비하기

  • 첫번째 방법은 저화질 이미지를 먼저 띄우는 방법이다.
  • 아래 사진은 실제로 띄울 이미지인데, 이 이미지의 저화질도 준비한다.



B. 저화질 먼저 적용하기

  • img의 src에 저화질 이미지를 먼저 적용한다.
<!--html-->
<img class="image" src="저화질_이미지_경로" />
  • css에서 image의 크기를 설정한다.
/*css*/
.image {
  width: 300px;
}



C. js에서 load 이벤트 사용하기

a. load이벤트?

  • 브라우저에 입장 혹은 퇴장할 때 발생하는 이벤트가 있다.
  • 사용자가 사이트 입장시, DomContentLoadedload 이벤트가 발생하며
  • 사용자가 사이트를 퇴장하려할 때, beforeunloadedunload이벤트가 발생한다.

  • 이 중 우리는 리소스가 로드되고 난 후 발생하는 load 이벤트를 이용해야 한다.
  • 고화질 이미지의 load 이벤트가 완료되면, imagesrc를 고화질로 변경하는 방식으로 진행해보자.

b. 이미지 로드시 고화질로 바꾸자!

  • 먼저 image 태그를 querySelector로 가져오자.
const img = document.querySelector('.image');

  • path변수에 고화질 이미지의 경로를 담는다.
const path = "고화질_이미지_경로";

  • changeImg()에서 이미지 경로를 고화질로 변경하도록 한다.
function changeImg() {
  img.src = path;
}

  • loadImg()에서는 new Image를 사용해 이미지객체를 생성한다.
function loadImg() {
  const newImg = new Image();   //this
  ...
}

  • 그 다음, 이 이미지 객체(newImg)에 고화질 이미지 경로를 적용한다.
function loadImg() {
  const newImg = new Image();
  newImg.src = path; //this
}

  • newImg가 load가 되면 (이미지 경로를 고화질로 변경하는)addImg를 실행한다.

(이 코드에서는 이미지 변화를 뚜렷히 보기 위해 setTimeout를 2초 걸었음(실제로 이용시 삭제 필요) )

function loadImg() {
  const newImg = new Image();
  newImg.src = path;
  newImg.addEventListener('load', function() {   //this
    setTimeout(changeImg, 2000);
  });
}

loadImg();  //실행

c. 결과 보기

See the Pen image preload event by KumJungMin (@kumjungmin) on CodePen.





2. skeleton loading 사용하기

A. skeleton loading이란

  • skeleton loading은 리소스가 랜더링 되기 전, 컨텐츠의 레이아웃을 먼저 보여주는 방식이다.
  • 대표적으로 페이스북, 인스타그램에서 화면 로딩시 사용하는 방식이다.




B. skeleton loading 만들기

a. html에 컨텐츠 영역 만들기

  • html에서 컨텐츠를 나타낼 영역을 만든다.
<div class="placeholder"></div>

b. background로 skeleton loading 만들기

  • 먼저 placeholder, image의 너비, 높이 등을 지정한다.

.placeholder {
  margin: 0 auto;
  width: 20rem;
  height: 20rem;
  overflow: hidden;
  box-shadow: 10px 10px 20px 5px rgba(0,0,0, 0.1);
}
.image {
  height: 100%;
}

여기서는 이미지load가 끝나면 <img>placeholder의 자식으로 추가할 예정이다.
이 말은 이미지 로드 전에 placeholder는 자식을 가지지 않는다는 말이다.

우리는 placeholder에 자식이 없을 때 로딩 화면을 띄울 것이다. 그렇다면 자식이 없을 때 스타일을 지정할 수 없을까? 있다! 바로 empty 선택자이다.
empty는 특정 dom의 자식은 물론 텍스트(띄어쓰기도 포함)도 없는 경우의 스타일을 지정할 수 있다! 한 번 만들어보자!


c. empty 선택자에서 로딩 만들기

  • skeleton loading은 background를 이용해서 만들 수 있다.
  • linear-gradient(방향, 색상1, 색상2, 색상3)를 이용해서 아래와 같은 선형 그라디언트 배경을 만든다.
  • 마지막으로 배경색의 사이즈는 100%로 한다.

.placeholder:empty {
  background: linear-gradient(to right, #eeeeee 10%, #dddddd 28%, #eeeeee 53%);
  background-size: 100%;
}

d. 애니메이션 추가하기

  • 우리가 보던 로딩화면을 만들기 위해서는 애니메이션이 필요하다.
  • 이 애니메이션은 간단한데, 바로 background의 위치를 이동시키기만 하면 된다. 🙂
@keyframes loadingAnimation{  //배경색 위치 이동하는 애니메이션
  0%{
    background-position: -20rem 0;  
  }
  100%{
    background-position: 20rem 0;
  }
}
.placeholder:empty {
  animation: 2s loadingAnimation forwards infinite linear;  //애니메이션 적용
}

  • 애니메이션을 적용하면 아래와 같은 모습이 된다.



C. js에서 이미지 적용하기

a. 필요한 요소 준비하기

  • placeholder가 필요하므로 querySelector로 가져온다.
  • document.createElement를 사용해 img 요소를 만든다.
const imgArea = document.querySelector('.placeholder');
let img = document.createElement('img');

b. addImg()에서 자식 추가하기

  • 생성한 img요소를 imgArea의 자식으로 추가하는 이벤트를 만든다.
function addImg() {
  imgArea.appendChild(img);
}

c. loadImg()에서 고화질 적용하기

  • img요소에 image 클래스를 추가해 스타일을 지정한다.
  • 그 다음 고화질 이미지 주소를 적용한다.
function loadImg() {
  img.classList.add('image');
  img.src = "고화질_이미지_주소";
  ...
}

  • imgload가 되면, addImg메소드를 실행한다.

(이 코드에서는 이미지 변화를 뚜렷히 보기 위해 setTimeout를 2초 걸었음(실제로 이용시 삭제 필요))

function loadImg() {
  ...
  img.addEventListener('load', function() {  //this
    setTimeout(addImg ,2000);
  })
}

loadImg();

d. 결과 보기

See the Pen image skeleton loading by KumJungMin (@kumjungmin) on CodePen.





출처
아래 링크로 이동하면 더 자세히 알 수 있다다ㅏㅏ

반응형

댓글