웹솔루션개발 25년 노하우! 해피CGI의 모든것

[해피CGI][cgimall] Vue.js 반응형 셔플 이미지 갤러리 본문

웹프로그램밍 자료실/HTML 자료

[해피CGI][cgimall] Vue.js 반응형 셔플 이미지 갤러리

해피CGI윤실장 2025. 8. 25. 09:05

Vue.js를 활용해 반응형으로 동작하며, 이미지 배열을 셔플(Shuffle)하는 갤러리
이 CodePen 예제는 Vue.js를 사용하여 반응형 레이아웃과 동적인 이미지 배열 기능을 구현한 셔플 갤러리입니다.

포트폴리오 갤러리, 상품 이미지 목록, 이벤트나 캠페인 사진 전시 활용하면 유용합니다.

HTML 구조

<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>

 

<div id='app'>

  <ul class='gallery'>

    <li

      v-for='item in items'

      :key='item.id'

      :data-pos='item.pos'

      :style='{

        translate: `calc(var(--width) * 0.2 * ${item.pos})`,

        scale: item.scale,

        backgroundImage: `url(${item.url})`

      }'

      @click='shuffle(item)'

    >

    </li>

  </ul>

</div>



CSS 소스

:root {

  --width: min(1000px,90vw);

}

 

* {

  margin: 0;

  padding: 0;

  box-sizing: border-box;

}

 

#app {

  height: 100vh;

  display: grid;

  place-items: center;

}

 

.gallery {

  width: min(var(--width));

  list-style-type: none;

  display: grid;

 

  & li {

    position: relative;

    grid-column: 1;

    grid-row: 1;

    width: calc(var(--width) / 5);

    aspect-ratio: 1;

    cursor: pointer;

    background-position: center;

    background-size: cover;

    background-repeat: no-repeat;

    box-shadow: 0 2px 7px rgba(0,0,0,0.6);

    transition: translate 0.8s, scale 0.8s;

    will-change: transform;

 

    &::after {

      content: '';

      position: absolute;

      inset: 0;

      background-color: rgba(0,0,0,0.6);

    }

  }

 

  & li[data-pos='0'] { scale: 1; z-index: 1; }

  & li[data-pos='1'] { scale: 1.4; z-index: 5; }

  & li[data-pos='2'] { scale: 1.8; z-index: 10; }

  & li[data-pos='3'] { scale: 1.4;  z-index: 5; }

  & li[data-pos='4'] { scale: 1; z-index: 1; }

 

  & li[data-pos='1']::after { background-color: rgba(0,0,0,0.4); }

  & li[data-pos='2']::after { background-color: transparent; }

  & li[data-pos='3']::after { background-color: rgba(0,0,0,0.4); }

}



JS 소스

const {createApp,reactive} = Vue;

 

createApp({

  setup() {

    const items = reactive([

      {id: 0, pos: 0, url: 'https://tinyurl.com/4e6sb4eu'},

      {id: 1, pos: 1, url: 'https://tinyurl.com/2mj4ybmz'},

      {id: 2, pos: 2, url: 'https://tinyurl.com/y75eb7sx'},

      {id: 3, pos: 3, url: 'https://tinyurl.com/363twa27'},

      {id: 4, pos: 4, url: 'https://tinyurl.com/3cksf5nf'},

    ]);

 

    function shuffle(item) {

      const heroPos = Math.floor(items.length/2);

      const hero = items.findIndex(({pos}) => pos === heroPos);

      const target = items.findIndex(({id}) => id === item.id);

      [items[target].pos,items[hero].pos] = [items[hero].pos,items[target].pos];

    }

 

    return {

      items,

      shuffle,

    }

  },

}).mount('#app');

 

Comments