라이브러리에 추가할 컴포넌트를 생각해보다 이전에 시간이 없어서 스킵하고 넘어간 Masonry
레이아웃을 한번 만들어 보았습니다.
Masonry
레이아웃은 벽돌과 같은 형태로 대표적으로 핀터레스트에서 사용하고 있는 형태로, 이미지를 나열하는데 사용하면 좋은 레이아웃 입니다!
생각한 방법은 아래와 같습니다.
배치할 요소를 순회하면서 각 요소들의 위치를 계산 합니다. 그 후 요소들을
translate
속성을 이용해 배치시킵니다.
위 방법대로 구성하기 위해, 2가지 데이터가 필요하였고, 그 데이터를 아래와 같습니다.
height
값column
의 높이요소의 height
를 현재 가장 낮은 column
에 추가하며 그 값을 토대로 해당 요소의 position
을 계산합니다.
const positionUpdate = useCallback(() => {
columnHeights.current = Array(column).fill(0);
const positions = itemsRef.current.map(item => {
const itemWidth = item.offsetWidth;
const minHeightColumn = columnHeights.current.indexOf(
Math.min(...columnHeights.current)
);
const x = itemWidth * minHeightColumn + gap * minHeightColumn;
const y = columnHeights.current[minHeightColumn];
columnHeights.current[minHeightColumn] += item.offsetHeight + gap;
return { x, y };
});
setMaxHeight(Math.max(...columnHeights.current));
setItemPositions(positions);
}, [column, gap]);
위 함수를 통해 children
을 순회하며 position
을 계산하였습니다.
요소들의position
은 absolute
이며, 요소들은 translate
를 통해 조작되고 있습니다.
그렇기 때문에 상위 컴포넌트에서 height
가 0으로 인식되는 문제가 발생하여 이 문제를 해결하기 위해 column의 가장 높은 height
를 기록하여 상위 컴포넌트의 height
로 할당해주었습니다.
Masonry
레이아웃의 경우, 이미지를 나열하는, 즉 무한스크롤
과 같이 사용될 가능성이 높은 컴포넌트 입니다. 이 경우 대비해 추 후 렌더링 적인 측면을 더 보완하는 작업이 필요할 것 같습니다.