taenykim / 3d-space-carousel

๐ŸŒŒ 3d space image carousel with nuxt

Home Page:https://3d-space-carousel.vercel.app/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

3d space carousel

๐ŸŒŒ 3d space image carousel with nuxt

Vue ๊ณต๋ถ€๋ฅผ ์œ„ํ•ด ๋งŒ๋“ค์–ด๋ณธ ํ† ์ด ํ”„๋กœ์ ํŠธ

๐Ÿ“ ํ”„๋กœ์ ํŠธ ์„ค๋ช…

  • ๊ธฐ์ˆ ์Šคํƒ : Nuxt, Vue
  • ์˜๋„ : Vue ์ฒดํ—˜ ๋ฐ ๊ณต๋ถ€
  • ๋ฐฐํฌ ์‚ฌ์ดํŠธ : https://3d-space-carousel.vercel.app/

๐Ÿ“™ ๋ฐฐ์šด๋‚ด์šฉ ์ •๋ฆฌ(Vue)

Vue vs React

  • ์“ฐ๊ธฐ ๋‚˜๋ฆ„์ด๊ฒ ์ง€๋งŒ, React๋Š” jsx ๋ฌธ๋ฒ•์œผ๋กœ html์„ ํ•จ์ˆ˜์ธ์Šคํ„ด์Šค ๋‚ด๋ถ€์—์„œ JavaScript๋กœ ๋ชจ๋‘ ์ž‘์„ฑํ•˜์˜€๋‹ค๋ฉด Vue๋Š” template ๋‚ด๋ถ€์—์„œ html๋ฌธ๋ฒ•์„ ๋”ฐ๋กœ ์ ์–ด์ฃผ์—ˆ๋‹ค. ๋ทฐ์™€ ๋กœ์ง์„ ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„๋กœ ๊ด€๋ฆฌํ•œ๋‹ค๋Š” ๊ฒƒ์€ ๋น„์Šทํ•œ ๊ฒƒ ๊ฐ™์•˜๋‹ค.
  • React๋Š” setState ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝ, ๊ฐ์ง€๋ฅผ ํ–ˆ๋‹ค๋ฉด, Vue๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋ƒฅ ๋ฐ”๊พธ๋ฉด ์•Œ์•„์„œ ๊ฐ์ง€ํ•ด์ฃผ๋Š” ๊ฒƒ ๊ฐ™์•˜๋‹ค.

style

  • Vue ํŒŒ์ผ ๋‚ด๋ถ€์—์„œ styleํƒœ๊ทธ์— scoped ๋ฅผ ์ ์–ด์ฃผ๋ฉด ๋ชจ๋“ˆํ™”๊ฐ€ ๋ฐ”๋กœ ๊ฐ€๋Šฅํ•˜๊ณ , lang="scss"๋ฅผ ์ ์–ด์ฃผ๋ฉด ์ „์ฒ˜๋ฆฌ๊ธฐ๋„ ๋ฐ”๋กœ ์“ธ ์ˆ˜ ์žˆ์–ด์„œ ์ƒ๋‹นํžˆ ํŽธํ–ˆ๋‹ค. ๋ฌผ๋ก  sass๋ฅผ ์„ค์น˜ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค!

Nuxt

  • pages : ํŽ˜์ด์ง€ ์„œ๋ฒ„์‚ฌ์ด๋“œ๋ Œ๋”๋ง๊ณผ ๋ผ์šฐํŒ…์„ ์ง€์›ํ•œ๋‹ค. ๋™์ ๋ผ์šฐํŒ…๋„ _ ์“ฐ๋ฉด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • layouts : ํŽ˜์ด์ง€ ๊ณตํ†ต๋ถ€๋ถ„์„ ๊ตฌ์„ฑํ•ด์ค€๋‹ค. <Nuxt/> ์ปดํฌ๋„ŒํŠธ ์•ˆ์œผ๋กœ page๊ฐ€ ๋“ค์–ด๊ฐ€๋Š” ๊ฒƒ ๊ฐ™๋‹ค.
  • components : ์ปดํฌ๋„ŒํŠธ๋“ค
  • assets, static : ์—์…‹์€ ๋นŒ๋“œ์‹œ ๋“ค์–ด๊ฐ€๋Š” ์ •์ ํŒŒ์ผ, ์Šคํƒœํ‹ฑ์€ ๊ทธ๋ ‡์ง€ ์•Š์€ ์ •์ ํŒŒ์ผ์„ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค. ๊ณต์‹๋ฌธ์„œ์— ์ฐจ์ด์ ์ด ๋‚˜์™€์žˆ๋‹ค.

๋ฐ˜๋ณต๋ฌธ

  • Vue๋Š” ์•„๋ž˜์˜ ๋ฐฉ์‹์œผ๋กœ ๋ฐ˜๋ณต๋ฌธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.
<Component v-for="imageSrc of imageSrcs"
<Component v-for="(imageSrc,index) of imageSrcs"`
  • React๋Š” ์•„๋ž˜์˜ ๋ฐฉ์‹์œผ๋กœ ๋ฐ˜๋ณต๋ฌธ์„ ์‚ฌ์šฉํ–ˆ๋˜ ๊ฒƒ์œผ๋กœ ๊ธฐ์–ตํ•œ๋‹ค.
{{imageSrcs.map(imageSrc=> <Component>)}}

์•ฝ์–ด

  • props, key, style ๋“ฑ๋ก
<Component v-vind:something="value" />
<Component :something="value"/>
  • ์ด๋ฒคํŠธํ•ธ๋“ค๋Ÿฌ ๋“ฑ๋ก
<Component v-on:eventName="handler"/>
<Component @eventName="handler"/>

CSR ๋ผ์šฐํŒ…

  • <nuxt-link/>๋ฅผ ์“ฐ๋ฉด ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ๋กœ ๋ผ์šฐํŒ…ํ•ด์ค€๋‹ค.
  • ๋™์ ๋ผ์šฐํŒ… : ํŒŒ์ผ๋ช… ์•ž์— _๋ฅผ ๋ถ™์—ฌ์ค€๋‹ค.
  • params ์ƒํƒœ๋“ฑ๋ก : asyncData({ params }) {}
  • validation : validate({ params }) {}

Vue ์ธ์Šคํ„ด์Šค

<script> ์•ˆ์˜ export default {} ๋‚ด๋ถ€์—์„œ ์ธ์Šคํ„ด์Šค ์˜ต์…˜์„ ์ ์–ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

  • lifecycle hook (created, mounted) : ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ๋ถ€ํ„ฐ ์†Œ๋ฉธ ์‹œ์ ๊นŒ์ง€์˜ ๋ผ์ดํ”„์‚ฌ์ดํด
  • data : ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€ ์ƒํƒœ
  • watch : ์ƒํƒœ์˜ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€
  • methods : ์ธ์Šคํ„ด์Šค ๋‚ด๋ถ€ ๋ฉ”์†Œ๋“œ
  • props : ๋ถ€๋ชจ์—๊ฒŒ์„œ ๋„˜์–ด์˜จ props

DOM ์กฐ์ž‘

  • dom์„ ์กฐ์ž‘ํ•  ๋•Œ, this.$refs ๋กœ ์กฐ์ž‘๊ฐ€๋Šฅํ•˜๋‹ค.

๐Ÿ“š ๋ฐฐ์šด๋‚ด์šฉ ์ •๋ฆฌ(๊ทธ ์™ธ)

3d carousel

  • perspective : z์ถ•์„ ๋”ฐ๋ผ view์™€ ๊ด€์ฐฐ์ž์˜ ๊ฑฐ๋ฆฌ(๊นŠ์ด๊ฐ)์„ ๋‚˜ํƒ€๋ƒ„ (ํ”ฝ์…€ ๊ธฐ๋ฐ˜)
  • ๊ด€์ฐฐ์ž ์‹œ์  3d๋กœ ์„ค์ • : transform-style: preserve-3d;
  • perspective ๋ฅผ ๋ถ€๋ชจ์— ์„ค์ •ํ•˜๋Š๋ƒ ๊ฐœ๋ณ„ ์ž์‹์— ์„ค์ •ํ•˜๋Š๋ƒ์— ๋”ฐ๋ผ์„œ ๋‹ค๋ฅธ 3d ํšจ๊ณผ๋ฅผ ์ค„ ์ˆ˜ ์žˆ์Œ.
  • 3d carousel์€ wrapper์ธ .image-container์— perspective๋ฅผ ์„ค์ •ํ•˜๊ณ , .carousel์— 3d ์†์„ฑ์„ ์ฃผ์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  .carousel > .image-button์— YํšŒ์ „๊ฐ’(๊ฐ๋„์— ๋”ฐ๋ผ ์ผ์ •ํ•˜๊ฒŒ ํšŒ์ „)๊ณผ ZํšŒ์ „๊ฐ’(๋ถ€๋ชจ carousel๋ถ€ํ„ฐ์˜ ๊ฑฐ๋ฆฌ)๋ฅผ ์ฃผ์—ˆ๋‹ค.
.image-container {
  perspective: 1000px;
}

.carousel {
  // ์ด๋ฏธ์ง€๋“ค์„ ํฌ๊ฒŒ ๋ณด๊ธฐ์œ„ํ•จ!
  transform: translateZ(900px);
  // carousel ์ž์ฒด ํšŒ์ „
  transform: rotateY(${angle}deg)
  transform-style: preserve-3d;
}

.image-button {
  // rotateY : ์ด๋ฏธ์ง€ ๋งˆ๋‹ค์˜ ํšŒ์ „๊ฐ’
  // rotateZ : ๋ถ€๋ชจ์ธ carousel์—์„œ์˜ ๊ฑฐ๋ฆฌ
  transform: rotateY(${rotateDeg}deg) translateZ(288px);
}

์Šคํฌ๋กค๋ฐ” ์ปค์Šคํ„ฐ๋งˆ์ด์ง•

::-webkit-scrollbar {
  width: 8px;
}

/* Track */
::-webkit-scrollbar-track {
  border-radius: 4px;
}

/* Handle */
::-webkit-scrollbar-thumb {
  background: #ffffff88;
  border-radius: 4px;
}

/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
  background: white;
}

โ›๏ธ ์‚ฝ์งˆํ•œ ๊ฒƒ

๋ผ์šฐํŒ… ์‹œ, ํŠน์ • ์ปดํฌ๋„ŒํŠธ๋งŒ ๋ Œ๋”๋ง

  • ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ผ์šฐํŒ…์„ ํ•˜๋ฉด์„œ, ํŠน์ • ์ปดํฌ๋„ŒํŠธ๋งŒ ๋ฆฌ๋ Œ๋”๋งํ•˜๊ณ  ์‹ถ์€๋ฐ, ๋ผ์šฐํŒ…์ด ๋˜๋ฉด nuxt์˜ page ๊ฐ€ ๋ชจ๋‘ ๋ Œ๋”๋ง ๋˜์—ˆ๋‹ค.
  • <NuxtChild> ๋ฅผ ์จ์„œ ํ•ด๊ฒฐ
  • pages ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด๋ถ€์—์„œ index ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ , ๋™์ ๋ผ์šฐํŒ…๋  ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋”ฐ๋กœ ์ ์–ด์ฃผ๋‹ˆ๊นŒ ๋ผ์šฐํŒ…๋˜์–ด๋„ child์•ˆ์— ์žˆ๋Š” vue๋งŒ ๋ Œ๋”๋ง ๋˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ๊ทธ๋Œ€๋กœ ์žˆ์—ˆ๋‹ค. ์–ด๋–ค ๋ฐฉ์‹์ธ์ง€๋Š” ์ดํ•ดํ–ˆ๋Š”๋ฐ ์•„์ง ์ต์ˆ™ํ•˜์ง„ ์•Š์€ ๊ฒƒ ๊ฐ™๋‹ค.
  • ์ฐธ๊ณ ํ•œ ์‚ฌ์ดํŠธ : https://ednsquare.com/story/nested-routes-in-nuxt-js-with-example------ayGs0r

์ด๋ฏธ์ง€ ๊นœ๋นก๊ฑฐ๋ฆผ

  • ์ด๋ฏธ์ง€๋ฅผ ์ผ๋ถ€๋Ÿฌ ๊ณ ํ•ด์ƒ๋„๋ฅผ ์ผ๋Š”๋ฐ, ์ด๋ฏธ์ง€๋กœ๋”ฉ์‹œ, ๊นœ๋นก๊ฑฐ๋ฆผ์ด ์žˆ๋‹ค. ์ด๋ฏธ์ง€ ์ดˆ๊ธฐ๋กœ๋”ฉ ํ›„์—๋Š” ์บ์‹ฑ์ด ๋˜์„œ ๋œํ•˜๊ธด ํ•˜๋Š”๋ฐ ์™„๋ฒฝํžˆ ๊นœ๋นก๊ฑฐ๋ฆผ์„ ์—†์•จ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์„๊นŒ?
const bgImg = new Image();
bgImg.onload = () => {
  this.$refs.imageButton.style.backgroundImage = "url(" + bgImg.src + ")";
};
bgImg.src = this.src;

์ด ๋ฐฉ๋ฒ•๋„ ์‹œ๋„ํ•ด๋ดค๋Š”๋ฐ ๊นœ๋นก๊ฑฐ๋ฆผ์ด ๋‚จ์•„์žˆ๋‹ค.

๐Ÿ”— reference

About

๐ŸŒŒ 3d space image carousel with nuxt

https://3d-space-carousel.vercel.app/


Languages

Language:Vue 78.0%Language:TypeScript 13.4%Language:JavaScript 8.4%Language:SCSS 0.1%