-
masonry / infinite scroll / imagesLoaded 활용하여 핀터레스트 | 네이버 이미지 리스트화면 구현하기쬬는 개발중 2022. 12. 9. 16:27반응형
벽돌처럼 차곡차곡쌓아진
디자인을 masonry 라고 이야기한다. 이번엔 사이즈가 제각각 다른 이미지를 활용해 이런 피드리스트를 구현해보았다. 추가로 스크롤링시 다음 페이지를 호출하는 방식을 사용했다. (infinite scroll)
핀터레스트 네이버 masonry 만 사용한 경우
발생되는 문제점이 애초에 해당 프로젝트는 pull-refresh 를 사용하고 있어서 제대로 영역을 감지 못하는 상태였다. 게다가 데이터 내부에 이미지를 받아오자마자 뿌려주다보니 이미지가 완전히 load 되기 전에 레이아웃이 실행되어 높이 영역이 계속해서 겹치는 현상이 발생했다. 그럼 어떻게 해결할 수 있을까? 라는 생각을 이것저것 해보다가 이미지가 완전히 load 되어 높이가 지정되었을 때, 적용하면 문제없이 구현이 가능할것이라고 생각했다.
사용 라이브러리
👉 masonry
Masonry
Install Download CDN Link directly to Masonry files on unpkg. Package managers Install with Bower: bower install masonry --save Install with npm: npm install masonry-layout Getting started HTML Include the Masonry .js file in your site. Masonry works o
masonry.desandro.com
👉 vue-image-loaded
리액트나 다른 구성이면 맞춰서 사용하면 된다
vue-images-loaded
Vue.js 2.0 directive to detect image loading. Latest version: 1.1.2, last published: 6 years ago. Start using vue-images-loaded in your project by running `npm i vue-images-loaded`. There are 7 other projects in the npm registry using vue-images-loaded.
www.npmjs.com
👉 패키지 설치
npm install masonry-layout npm install vue-images-loaded
👉 index.vue
import Masonry from "masonry-layout"; import ImagesLoaded from "imagesloaded";
👉 html or template
<div id="grid"> <div class="box" v-for="(item, index) in boxItem" :key="index"> <img :src="item.src" /> </div> </div>
👉 script
data(){ return { boxItem: [], page: 1, } }, mounted(){ this.getData(); // 초기 데이터 호출 window.addEventListener("scroll", this.handler); // 스크롤 시 호출 }, methods:{ getData(){ axios.get('url',params).then((data)=>{ // boxItem에 담을 요소를 넣어준다 this.boxItem = [...this.boxItem, ...data.arr ]; // boxItem 기준으로 grid 생성 this.$nextTick(() => { this.createGrid();} this.timeLoading = false; this.bottomLoading = false; }) }, createGrid() { if (!this.boxItem.length > 0) return; this.$nextTick(() => { this.imagesLoaded(); }); }, imagesLoaded() { const grid = document.querySelector("#grid"); return new ImagesLoaded(grid, () => { this.$nextTick(() => { // 이미지 로드 후 masonry 호출 this.masonry(); }); }); }, masonry() { const grid = document.querySelector("#grid"); new Masonry(grid, { percentPosition: true, itemSelector: ".box", }); }, async handler() { if (this.timeLoading === false) { this.scroll = window.scrollY; const SCROLLED_HEIGHT = window.scrollY; const WINDOW_HEIGHT = window.innerHeight; const DOC_TOTAL_HEIGHT = document.body.offsetHeight; const IS_BOTTOM = WINDOW_HEIGHT + SCROLLED_HEIGHT + 4000 >= DOC_TOTAL_HEIGHT; // 분기 조건 :: 호출중, 마지막 페이지가 아닌경우 if ( IS_BOTTOM && this.lastPage === false && // 마지막 페이지 체크 this.timeLoading === false // axios 호출 상태 체크 ) { this.timeLoading = true; setTimeout(() => { if (!this.lastPage) { let page = this.page + 1; this.page = page; this.getData(); // axios 호출 } }, 700); } } }, }
반응형'쬬는 개발중' 카테고리의 다른 글
[Vue Error] npm run serve 오류 vue-cli-service: command not found (0) 2023.06.24 [javascript] 모바일 검색창 숨기기 기능 구현 (터치 떨림 보정) (1) 2023.01.30 [axios] 엑셀 파일 다운로드 기능 구현하기 (0) 2022.12.04 [axios] 이미지 POST 기능이 제대로 동작하지 않을때 확인사항 (0) 2022.12.02 [javascript | Vue] 이미지 다운로드 기능 만들기 (canvas/url활용) (0) 2022.12.02