Open SeonHyungJo opened 5 years ago
오늘은 몇시간만에 겨우 만든 Masonry Layout를 소개하려고 합니다. 흔히 사람들이 핀터레스트 레이아웃이라고 알고 있는 것으로 스크롤이 끝에 닿으면 자동으로 사진들이 더 보여주는 기능입니다.
하단에 보이는 노란색 Div에 Intersection Observer를 걸어서 무한스크롤을 구현했으며 Grid Cell을 추가하는데 성능을 고려하여 insertAdjacentElement()를 사용하였습니다.
insertAdjacentElement()
무엇보다 CSS3 Grid Layout을 사용하여 반응형에도 좋으며 구현하는데 도움이 많이 되었습니다.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link rel="stylesheet" href="./index.css"> <script src="./index.js"></script> <title>Document</title> </head> <body> <div id="gridWrapper"></div> </body> <script> const INIT_COLUMN_SIZE = 5; // Grid Template Size const INIT_ROW_SIZE = 20; // Grid Template Size const MAX_CELL_COLUMN_SIZE = 3; // Grid Cell Size const MAX_CELL_ROW_SIZE = 10; // Grid Cell Size const ADD_CELL_SIZE = 20; // Create Cell Count // Init currentRowNumList const currentRowNumList = Array(INIT_COLUMN_SIZE).fill(1); // Create Wrapper Div const gridWrapper = document.querySelector("#gridWrapper"); // Create masonry Div const masonry = document.createElement("div"); masonry.id = "masonry"; masonry.style.gridTemplateColumns = `repeat(${INIT_COLUMN_SIZE}, 1fr)`; masonry.style.gridTemplateRows = `repeat(${INIT_ROW_SIZE}, 1fr)`; // Create scrollPoint Div const scrollPoint = document.createElement("div"); scrollPoint.id = "scrollPoint"; gridWrapper.insertAdjacentElement("afterbegin", masonry); gridWrapper.insertAdjacentElement("afterend", scrollPoint); // Make intersectionObserver to create add new grid cells const intersectionObserver = new IntersectionObserver(function (entries) { Promise.all(createGridCell(ADD_CELL_SIZE)).then(() => { console.log("Finish"); }) }); // start observing intersectionObserver.observe(document.querySelector("#scrollPoint")); </script> </html>
let standardColumnRect = 1; let standardRowRect = 1; const getRandomNum = maxNum => { return Math.ceil(Math.random() * maxNum); }; const addGridAction = () => new Promise(resolve => { let maxColSize = 1; for (let i = standardColumnRect; i < INIT_COLUMN_SIZE; i++) { if (currentRowNumList[i] > standardRowRect) { break; } maxColSize += 1; } const columnSizeCondition = maxColSize >= MAX_CELL_COLUMN_SIZE ? MAX_CELL_COLUMN_SIZE : maxColSize; const columnSize = getRandomNum(columnSizeCondition); const rowSize = Math.ceil(Math.random() * MAX_CELL_ROW_SIZE + 1); // Random Picture from https://source.unsplash.com/random const newDiv = document.createElement("div"); newDiv.style.gridColumn = `${standardColumnRect} / ${standardColumnRect + columnSize}`; newDiv.style.gridRow = `${standardRowRect} / ${standardRowRect + rowSize}`; newDiv.style.backgroundImage = "url('https://source.unsplash.com/random')"; newDiv.style.backgroundSize = "cover"; newDiv.style.backgroundRepeat = "no-repeat"; newDiv.style.border = "1px solid black"; masonry.insertAdjacentElement("beforeend", newDiv); for (let i = standardColumnRect; i < standardColumnRect + columnSize; i++) { currentRowNumList[i - 1] += rowSize; } // Grid 우측 영역을 넘어가면 1로 초기화 standardRowRect = Math.min(...currentRowNumList); standardColumnRect = currentRowNumList.indexOf(standardRowRect) + 1; resolve(); }); const createGridCell = cellCount => { const promiseList = []; for (let i = 0; i < ADD_CELL_SIZE; i++) { promiseList.push(addGridAction()); } return promiseList; };
body{ margin: 0px; padding: 10px; } #masonry { display: grid; border: 3px solid black; gap: 20px; min-height: 120vh; margin: 0px; } #scrollPoint{ width: 100px; height: 100px; border: 1px solid yellow; background-color: yellow; }
오늘은 몇시간만에 겨우 만든 Masonry Layout를 소개하려고 합니다. 흔히 사람들이 핀터레스트 레이아웃이라고 알고 있는 것으로 스크롤이 끝에 닿으면 자동으로 사진들이 더 보여주는 기능입니다.
하단에 보이는 노란색 Div에 Intersection Observer를 걸어서 무한스크롤을 구현했으며 Grid Cell을 추가하는데 성능을 고려하여
insertAdjacentElement()
를 사용하였습니다.무엇보다 CSS3 Grid Layout을 사용하여 반응형에도 좋으며 구현하는데 도움이 많이 되었습니다.
index.js
index.css
시연