CSS&JS/⚡Thinkers

[CSS,JS] 3d-carousel slider(캐러샐 슬라이더)

arancia_ 2022. 10. 24. 15:00

 

네이버 모두가 지식인20니다. 홈페이지의 캐러셀 슬라이더가 인상깊어서 구현해보았음.

네이버 지식인20니다 캐러셀슬라이더

 

깃허브 : https://github.com/OhIkmyeong/carousel-v1/tree/main/mine-2-3d-reverse

 

GitHub - OhIkmyeong/carousel-v1: 캐러셀 슬라이더

캐러셀 슬라이더. Contribute to OhIkmyeong/carousel-v1 development by creating an account on GitHub.

github.com

데모 : https://ohikmyeong.github.io/carousel-v1/mine-2-3d-reverse/

 

모두지식인20니다 참고

 

ohikmyeong.github.io

참고 : https://3dtransforms.desandro.com/carousel

 

Carousel · Intro to CSS 3D transforms

Carousel Front-end developers have a myriad of choices when it comes to content carousels. May I suggest Flickity? Now that we have 3D capabilities in our browsers, why not give a shot at creating an actual 3D carousel? The markup for this demo takes the s

3dtransforms.desandro.com

 

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>모두지식인20니다 참고</title>
    <link rel="stylesheet" href="./carousel.css" type="text/css"/>
    <script src="./carousel.js" defer></script>
</head>
<body>
    
<div id="carousel-scene">
    <ul id="carousel">
        <li class="carousel-cell" style="--bg-color:red;">1</li>
        <li class="carousel-cell" style="--bg-color:orange;">2</li>
        <li class="carousel-cell" style="--bg-color:yellow;">3</li>
        <li class="carousel-cell" style="--bg-color:yellowgreen;">4</li>
        <li class="carousel-cell" style="--bg-color:lime;">5</li>
        <li class="carousel-cell" style="--bg-color:royalblue;">6</li>
        <li class="carousel-cell" style="--bg-color:blue;">7</li>
        <li class="carousel-cell" style="--bg-color:purple;">8</li>
        <li class="carousel-cell" style="--bg-color:violet;">9</li>
        <li class="carousel-cell" style="--bg-color:salmon;">10</li>
    </ul>
</div>
 
<div id="carousel-btns">
    <button data-direct="prev">prev</button>
    <button data-direct="next">next</button>
</div>
 
</body>
</html>
cs

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
@charset "utf-8";
*{margin:0;padding:0;box-sizing:border-box;}
li{list-style-type:none;}
html,body{
    overflow-x:hidden;
    display:flex;
    justify-content:center;align-items:center;
    width:100%;min-height:100vh;
}
#carousel-scene{
    outline:1px solid black;
    position:relative;
    width:100%; max-width:210px;
    aspect-ratio:16/9;
    perspective: 1200px;
}
 
#carousel{
    position:relative;
    width:100%;height:100%;
    transform-style: preserve-3d;
    transform:translateZ(1000px) rotateY(0deg);
    transition: transform 1s;
    cursor:grab;
}
 
.carousel-cell{
    --gap:10px;
    display:flex;justify-content:center;align-items:center;
    position:absolute;
    top:0;left:0;
    width:calc(100% - var(--gap)); height:100%;
    background:var(--bg-color);
    text-align:center;font-size:20px;font-weight:bold;
    user-select:none;
}
 
#carousel-btns{
    display:flex;
    justify-content:center;align-items:center;
    gap:10px;
    position:fixed;
    bottom:100px; left:50%;
    transform:translateX(-50%);
    font-size:20px;
}
#carousel-btns button{
    padding:.5em 1.5em;
    font-size:inherit;font-family:inherit;
    text-transform:uppercase;
    background:#000;color:#fff;
    border-radius:4px;
    cursor:pointer;
}
cs

JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
const $carousel = document.getElementById('carousel');
const $cells = Array.from($carousel.children);
const $btns = document.getElementById('carousel-btns');
const degY = 360 / $cells.length;
const widScene = document.getElementById('carousel-scene').offsetWidth;
const tz = Math.round(
    (widScene / 2/
    Math.tan(Math.PI / $cells.length)
);
let selectedIndex = 0;
const posX = {
    start: null,
    end: null
}
 
$cells.forEach(($cell, idx) => {
    const DEG = idx * degY;
    $cell.style.transform = `rotateY(-${idx * degY}deg) translateZ(-${tz}px)`;
});
 
$btns.addEventListener('click', e => {
    const direct = e.target.dataset.direct;
    if (!direct) return;
    rotate_carousel(direct);
});
 
 
$carousel.addEventListener('mousedown', (e) => {
    posX.start = e.clientX;
    $carousel.style.cursor = "grabbing";
});
 
$carousel.addEventListener('mouseup', (e) => {
    posX.end = e.clientX;
    const direct = posX.start - posX.end < 0 ? "prev" : "next";
    rotate_carousel(direct);
    $carousel.style.cursor = "grab";
});
 
function rotate_carousel(direct) {
    selectedIndex = direct == "prev" ? selectedIndex - 1 : selectedIndex + 1;
    const angle = degY * selectedIndex;
    $carousel.style.transform = `translateZ(1000px) rotateY(${angle}deg)`;
}//rotate_carousel
cs