Javascript - 그리드 레이아웃 이미지 교체 효과
Reference
핀터레스트에서 재미있는 효과를 봤습니다.
3X3의 그리드 레이아웃에서 이미지가 순차적으로 교체되는 효과인데, 단순하면서도 인상적입니다. 영상에서 많이 쓰이는 효과지만, 자바스크립트를 이용하면 웹에서도 비교적 수월하게 구현할 수 있습니다.
Preview
아래 영상은 실제로 구현했을 때 모습입니다. 순차적으로 이미지가 교체되는데, 약간의 딜레이를 주어서 다음 그리드 부분에서는 한 박자씩 늦게 교차되도록 구현합니다.
HTML
html은 아주 단순합니다. app이라는 id를 갖고 있는 main 태그에 내용이 삽입되도록 javascript에서 모든 부분을 제어합니다.
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<title>Photo Changer</title>
</head>
<body>
<main id="app"></main>
<script src="main.js" defer async type="module" ></script>
</body>
</html>
photo.json
간단한 더미 데이터를 마련해서 json 파일에 담아두었습니다. 이미지의 출처는 모두 pexels.com
에서 가져왔습니다.
{
"data": [
{
"id": 1,
"url": "https://images.pexels.com/photos/58997/pexels-photo-58997.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
},
{
"id": 2,
"url": "https://images.pexels.com/photos/4043573/pexels-photo-4043573.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
},
{
"id": 3,
"url": "https://images.pexels.com/photos/9335893/pexels-photo-9335893.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
},
{
"id": 4,
"url": "https://images.pexels.com/photos/9291125/pexels-photo-9291125.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
}
]
}
SCSS
스타일 시트 부분도 그다지 복잡하지 않은 구성입니다. 기본적인 배치는 grid
를 이용해서 4x3 그리드를 만들고 있습니다.
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@100;200;300;400;500;600;700;800;900&display=swap');
*{
margin:0;
padding:0;
box-sizing: border-box;
}
html,body{
width: 100%;
height: 100%;
font-family: 'Poppins', sans-serif;
}
body{
display: flex;
justify-content: center;
align-items: center;
}
img{
width: 100%;
max-width: 100%;
height: 100%;
object-fit: cover;
border:0;
}
#app{
--col : 4;
--row: 3;
--size: 800px;
display: grid;
grid-template-columns: repeat(var(--col), 1fr);
grid-template-rows: repeat(var(--row),1fr);
width:var(--size);
height:var(--size);
border-radius: 1vw;
overflow: hidden;
position: relative;
&::before,&::after{
width:100%;
height: 100%;
position: absolute;
top:0;
left:0;
}
&::before{
content: '';
background-color: hsla(220,50%,20%,0.5);
}
&::after{
display: flex;
align-items: center;
justify-content: center;
font-size: 5rem;
color: white;
text-transform: uppercase;
content: 'Happy Dogs'
}
figure{
height: 100%;
overflow:hidden;
}
}
Javascript
import photos from "./photo.json" assert {type: 'json'}
const {data} = photos
const delay = 500
// 주요 기능: 이미지와 이미지 변환기를 설정합니다.
const main = () => {
// app element를 가져옵니다.
const app = document.getElementById('app')
// app element 내부의 이미지 개수를 9개로 설정합니다.
setImages(app, 12)
// app element 내부의 모든 이미지를 가져와서 이미지 변환기에 설정합니다.
setChanger(Array.from(app.querySelectorAll('img')))
}
// 이미지들을 설정하는 함수
const setImages = (app, count) => {
// 이미지 개수만큼 반복
for (let i = 0; i < count; i++) {
// figure와 image 엘리먼트 생성
const figure = document.createElement('figure')
const image = document.createElement('img')
// 이미지를 figure에 추가
figure.appendChild(image)
// app에 figure 추가
app.appendChild(figure)
image.src= data[0].url; // 초기 이미지 설정
}
}
// 이미지 배열을 받아 타이머를 이용해 이미지를 변경하는 함수
const setChanger = (imageArray) => {
let timer; // 타이머 변수
imageArray.forEach((item, index) => {
timer = setTimeout(() => imageChanger(item,data,delay), delay * index); // 지연 시간에 따라 이미지 변경
});
};
/**
* 이미지를 주어진 데이터 배열의 url로 변경하는 함수
* @param {HTMLImageElement} image - 변경할 이미지 요소
* @param {Array} data - 이미지 URL을 포함하는 데이터 배열
* @param {number} delay - 이미지 변경 간격 (밀리초)
*/
const imageChanger = (image, data, delay) => {
let index = 0; // 데이터 배열의 인덱스
const timer = setInterval(() => {
if (index < data.length) {
image.src = data[index].url; // 이미지 소스 변경
index++; // 다음 데이터로 이동
} else {
clearInterval(timer); // 타이머 중지
}
}, delay);
}
window.addEventListener('load', main)
대략적인 작업의 흐름은 아래와 같습니다.
photo.json
에서 이미지 링크들을 가져와서 반복문을 이용해 배치하고, 순차적으로 교체하는 일을 하는 스크립트입니다.
delay
상수에서 이미지가 교체되는 빠르기
와 지연시간
을 모두 같이 쓰고 있습니다. 필요하다면 두 부분으로 나누는 것도 나쁘지 않습니다.
main
함수 안에서는 setImages
와 setChanger
함수를 호출하고 있는데, 각각 이미지를 배치하고, 그 배치된 이미지마다 순차적으로 교체되는 일을 하도록 작성했습니다.
setChanger
함수에서는 배치된 이미지들의 배열을 넘겨받아서, 그 배열 안에서 img
태그를 하나하나 꺼내 다시 imageChanger
함수로 각각의 이미지를 넘겨주는데, 그 안에서 setInterval
비동기 함수를 이용해 img
태그의 이미지를 순차적으로 교체하는 일을 합니다.
교체할 이미지는 photo.json
에서 가져옵니다.
그리고 마지막으로 전체적인 작업을 실행할 수 있는 main
함수를 호출하는 것으로 스크립트를 마무리합니다.