페이지에 백그라운드 이미지가 랜덤으로 보이게 해 보았다. 대화를 하다 아이디어를 얻었고 좋은 것 같아서 만들어보았다. 새로고침 할 때마다 이미지가 바뀌며, 시간이 지나면 안내 메세지는 사라진다. (아래의 gif는 블로그 포스팅을 위해 용량을 줄여 화질이 낮다.) 그럼 오늘은 간단히 어떻게 만들었나 정리해보겠다 🎵
✔️ Math 메서드를 이용해 랜덤 숫자 반환
우선 이미지 소스들을 배열로 모아 놓았기에 이 중에서 랜덤으로 이미지들을 선택해야했다. 그렇기에 먼저 랜덤 숫자를 구하기 위해 Math.random과 Math.floor를 사용했다.
* Math.random() 함수는 0 이상 1 미만의 구간에서 근사적으로 균일한 부동소숫점 의사 난수를 반환하며, 이 값은 사용자가 원하는 범위로 변형할 수 있다.
* Math.floor() 함수는 주어진 숫자와 같거나 작은 정수 중에서 가장 큰 수를 반환한다.
출처:mdn
위의 MDN의 설명처럼 Math.random()은 0 이상~ 1 미만 사이의 난수를 반환하고, Math.random() * 3을 할 경우 0 이상 3 미만의 난수를 반환하며 Math.floor는 소수점 이하 값을 버림 한다. 그렇기 때문에 Math.random과 함께 사용하면 랜덤의 숫자를 정수로 구할 수 있다.
위처럼 콘솔에서 확인할 수 있다.
const imageNumber = Math.floor(Math.random() * backgroundImage.length);
그래서 나는 backgroundImage라는 이미지 파일들을 모아 놓은 배열의 length 미만의 랜덤 숫자를 반환하도록 했다. 지금은 이미지가 3개여서 backgroundImage.length 대신 3이라는 숫자를 써도 되지만, 이미지를 계속 추가할 예정이어서 몇 개가 될지 몰라 backgroundImage.length로 작성하였다. const imageLength = 3;로 따로 선언하고 그 숫자를 바꾸는 방법도 있지만 우선은 위처럼 작성했다.
✔️ useState와 useEffect로 background image 수정하기
document.body의 style에 접근해 수정하는 방법과 useState를 사용하는 방법 모두 구현해보았다. dom을 직접 수정하는방법보다는 useState를 사용하는 것이 더 코드가 깔끔해 useState를 사용했다.
//Landing.js
import React, { useEffect, useState } from "react";
import { backgroundImage } from "asset/data";
export default function Landing() {
const [message, setMessage] = useState("");
const [image, setImage] = useState({});
const changeBackground = () => {
const imageNumber = Math.floor(Math.random() * backgroundImage.length);
const randomImage = backgroundImage[imageNumber];
setImage({
backgroundImage: `url(${randomImage})`,
});
};
useEffect(() => {
changeBackground();
setMessage("새로고침 할 때마다 새로운 이미지를 볼 수 있습니다.");
setTimeout(() => {
setMessage("");
}, 3000);
}, []);
return (
<div style={image} className="background">
<div className="refresh-message">{message}</div>
</div>
);
}
changeBackground 함수 안에서 랜덤 이미지를 구하는 방법은 아래의 순서와 같다.
* Math메서드를 사용해 이미지 소스를 모아 놓은 배열 안에서 랜덤으로 하나의 숫자를 반환하는 imageNumber를 구한다.
* 이미지들을 모아놓은 backgroundImage에서 imageNumber에 해당하는 이미지인 randomImage를 구한다.
* setImage를 이용해 backgroundImage의 url을 구한 randomImage로 설정해준다.
그리고 이 changeBackground를 useEffect를 이용해 화면이 렌더링될 때마다 실행해준다. 그리고 나는 화면에 새로고침 할 때마다 새로운 이미지를 볼 수 있다는 점을 안내 메세지로 잠깐 나타내고 싶어서 setTimeout을 통해 메세지가 나타났다 사라지게 하는 것까지 작성했다.
/* _Landing.scss */
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.background {
background-position: center;
background-repeat: no-repeat;
background-size: cover;
height: 100%;
animation: fadeIn 0.5s;
}
그리고 style을 모두 setImage에 줄 수 있지만, 그것보다는 scss파일에서 관리하는 것이 더 명확하기 때문에 backgroundImage외의 스타일은 모두 scss파일에서 관리했다. body의 background-color를 기본적으로 검정으로 주었다. 이미지가 바뀔 때 흰색보다 자연스럽기 때문이었다. 그런데 빠르게 새로고침을 할수록 검은 화면에 툭 이미지가 나오는 게 어색해서 fadeIn animation을 줘서 좀 더 자연스럽게 나타내고자 했다.
'📍 DEV > React & Next.js' 카테고리의 다른 글
useLayoutEffect (0) | 2021.11.24 |
---|---|
useRef & scrollIntoView (0) | 2021.11.20 |
React i18n-next를 이용한 다국어 처리 (0) | 2021.09.16 |