자바 스크립트 3D 슬라이드 - jaba seukeulibteu 3D seullaideu

이미지 슬라이더:3D 이미지 슬라이더 | 소스 코드와 함께 HTML CSS 및 JS를 사용하는 응답 터치 슬라이더


이 비디오에서는 소스 코드와 함께 HTML CSS 및 JS를 사용하여 이미지 슬라이더/3D 이미지 슬라이더/반응형 이미지 슬라이더를 단계별로 빌드합니다. HTML 및 CSS를 사용하여 이미지 슬라이더를 만드는 방법 | 소스 코드가 있는 이미지 슬라이드쇼 튜토리얼

Html CSS 및 JS를 사용한 반응형 터치 슬라이더 - JS를 사용한 3D 반응형 슬라이더 |HTML, CSS 및 Javascript로 이미지 슬라이더를 만드는 방법 | HTML, CSS 및 JavaScript를 사용하여 슬라이드쇼/캐러셀을 만드는 방법 | 순수 CSS 반응형 이미지 슬라이더 - HTML5/CSS3 튜토리얼


CSS,JS,SVG 및 이미지 다운로드: https://drive.google.com/file/d/1hENANTV4cHgQcKOXCmWwQW5aLlufZsoF/view?usp=sharing

#html #cs #자바스크립트



자바 스크립트 3D 슬라이드 - jaba seukeulibteu 3D seullaideu

www.youtube.com

이 비디오에서는 소스 코드와 함께 HTML CSS 및 JS를 사용하여 이미지 슬라이더/3D 이미지 슬라이더/반응형 이미지 슬라이더를 단계별로 빌드합니다. HTML 및 CSS를 사용하여 이미지 슬라이더를 만드는 방법 | 소스 코드가 있는 이미지 슬라이드쇼 튜토리얼

C++에서 시스템 일시 중지

 최근에 프론트앤드 업무를 하면서 3D 작업에 관심을 가지게 됐다. CSS를 이용해서 3D 효과를 많이 이용해보지 않았기 때문에 연습삼아 올려볼까 한다. 이번 포스팅에서 만들어 볼 예제는 캐러셀 슬라이드(Carousel Slide)다. 

완성본
자바 스크립트 3D 슬라이드 - jaba seukeulibteu 3D seullaideu

 완성본 영상처럼, 나는 1부터 9까지 총 9개의 아이템을 만들어 줄 것이다. 현재 실행 결과코드는 다음과 같다.

자바 스크립트 3D 슬라이드 - jaba seukeulibteu 3D seullaideu
[그림 1] 현재 실행 결과
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3D 이미지 캐러셀</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="scene">
    	<div class="carousel>
            <div class="item">1</div>
            <div class="item">2</div>
            <div class="item">3</div>
            <div class="item">4</div>
            <div class="item">5</div>
            <div class="item">6</div>
            <div class="item">7</div>
            <div class="item">8</div>
            <div class="item">9</div>
        </div>
    </div>
</body>
</html>
*{
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}

.item{
    width: 210px;
    height: 150px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px  solid black;
    color:#fff;
    font-size: 32px;
    font-weight: 600;
}

.item:nth-child(1){
    background-color: #ff7979;
}

.item:nth-child(2){
    background-color: #ffbe76;
}

.item:nth-child(3){
    background-color:#f0932b;
}

.item:nth-child(4){
    background-color:#7ed6df;
}

.item:nth-child(5){
    background-color:#e056fd;
}

.item:nth-child(6){
    background-color: #22a6b3;
}

.item:nth-child(7){
    background-color: #be2edd;
}

.item:nth-child(8){
    background-color:#4834d4;
}

.item:nth-child(9){
    background-color:#30336b;
}

 이제 현재 공간을 2D에서 3D로 변환시켜야한다. 이를 위해서는 화면에 원근감을 줘야한다. 원근감이란, 멀고 가까운 거리에 대한 느낌. 미술에서는 색채, 명암,  따위를 이용하여 원경, 중경, 근경의 느낌 나타낸다[출처: 네이버 국어사전].

이를 위해 item 요소의 부모인 scene 태그에 perspective 속성을 줘야한다. 

.scene{
	perspective: 1000px;
}

 똑같은 크기의 카드를 보더라도, 가까이 볼 때와 멀리서 볼 때의 크기는 다르게 보인다. perspective 속성 값을 높게 줄 수록, 원근감의 영향을 덜 받고 왜곡이 적다. 따라서 1000px의 값을 줬다. 하지만 이 속성을 부여했다해서 결과는 [그림 1]과 다를게 없을 것이다.

자바 스크립트 3D 슬라이드 - jaba seukeulibteu 3D seullaideu
[그림 2] perspective 속성에 따른 결과 값 비교(출처: css 변형 사용하기 MDN, https://developer.mozilla.org/ko/docs/Web/CSS/CSS_Transforms/Using_CSS_transforms)

 본론으로 돌아와보자. 현재 캐러셀 아이템 9 개다. 2D가 아니라 z축이 개입된 3D 환경이기 때문에 1부터 9까지 카드를 포개듯이 위치를 겹쳐야한다(그리고 외관상 보기 편하게하기 위해 수직, 수평 모두 가운데 정렬을 속성을 줬다). 이를 위한 CSS 코드와 적용된 결과는 다음과 같다.

.scene{
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    perspective: 1000px;
    transform-style: preserve-3d;
}

.carousel{
    width: 210px;
    height: 150px;
    position: relative;
}

.item{
    position: absolute;
    top: 0;
    left: 0;
    width: 210px;
    height: 150px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px  solid black;
    color:#fff;
    font-size: 32px;
    font-weight: 600;
}
자바 스크립트 3D 슬라이드 - jaba seukeulibteu 3D seullaideu
[그림 3] 수직, 수평 가운데 정렬 효과 적용

정구각형 형태로 나타내기 위해서는 Y축에 40(360/9)만큼의 각도를 부여해주면 된다.

.item:nth-child(1){
    background-color: #ff7979;
    transform: rotateY(0deg);
}

.item:nth-child(2){
    background-color: #ffbe76;
    transform: rotateY(40deg);
}

.item:nth-child(3){
    background-color:#f0932b;
    transform: rotateY(80deg);
}

.item:nth-child(4){
    background-color:#7ed6df;
    transform: rotateY(120deg);
}

.item:nth-child(5){
    background-color:#e056fd;
    transform: rotateY(160deg);
}

.item:nth-child(6){
    background-color: #22a6b3;
    transform: rotateY(200deg);
}

.item:nth-child(7){
    background-color: #be2edd;
    transform: rotateY(240deg);
}

.item:nth-child(8){
    background-color:#4834d4;
    transform: rotateY(280deg);
}

.item:nth-child(9){
    background-color:#30336b;
    transform: rotateY(320deg);
}

결과는 다음과 같다.

자바 스크립트 3D 슬라이드 - jaba seukeulibteu 3D seullaideu
[그림 4] Y축 방향으로 40도 씩 각도를 줬을 경우

 [그림 4]를 보자. 왼쪽은 단순히 위 코드를 실행시켰을 경우의 그림이고, 오른쪽은 .scene 클래스에서 x축 방향으로 85도(45도)만큼의 각도를 준 그림이다. 오른쪽 그림을 보여준 이유는 각 블록을 정구각형 형태로 만들기 위해서다. [그림 4]의 오른쪽 그림을 자세히 보면 다음과 같다.

자바 스크립트 3D 슬라이드 - jaba seukeulibteu 3D seullaideu
[그림 5] 그림 4의 오른쪽 그림의 각 선분의 끝 선을 이어보면 정구각형 형태의 그림이 완성된다.

 [그림 5]는 정구각형이다. 그리고 우리가 이상적으로 생각하는 캐러셀 슬라이드를 만들기 위해서는 정 구각형의 각 모서리의 너비가 210픽셀이 되야한다. [그림 4]를 보면 가운데 꼭지점을 중심으로 [그림 5]와 같이 꼬여있는 형태가 되어있는 것을 알 수 있다. 따라서 우리는 원근법을 이용해서 파란색 선분이 있는 위치를 노란색 화살표 길이만큼 이동하여 정구각형 모서리를 210px만큼 만들어줘야한다. 노란색 선분 길이를 구하기 위해서는 간단하게 삼각함수를 이용하면 된다.

자바 스크립트 3D 슬라이드 - jaba seukeulibteu 3D seullaideu
[그림 6] 정구각형의 한 부분

 노란색 선분을 구하기 위해서는 [그림 6]을 보면 된다. 밑면의 길이는 210픽셀이다. 이를 반으로 나누면 105픽셀이 된다. 그리고 삼각형의 각도는 40도지만, 반으로 나누면 20도가 된다. 따라서 선분의 값은 105/tan20의 값인 288.485가 된다. 따라서 각 아이템 값에 translateZ(288px) 속성을 부여하면 된다. 그리고 각 블록마다 간격을 주기 위해서 너비 값을 210픽셀에서 200픽셀로 바꾸었다.

자바 스크립트 3D 슬라이드 - jaba seukeulibteu 3D seullaideu
[그릠 7] 캐러셀 슬라이드

 캐러셀 슬라이드가 완성됐다. 회전을 주기위해서는 y축 방향으로 40도씩 이동을 하면된다. 아니면 애니메이션 값을 주면 된다.

.carousel{
    width: 220px;
    height: 150px;
    position: relative;
    transform-style: preserve-3d;
    animation: spin 5s infinite linear;
}

@keyframes spin{
    from{
        transform: rotateY(0deg);
    }
    to{
        transform: rotateY(360deg);
    }
}

.scene 클래스 안에서 transform-style:preserve-3d 값을 .carousel 클래스 안으로 설정해주었다. 왜냐하면 .scene클래스 안에서 저 값을 설정해줄 경우, 캐러셀 슬라이더가 회전하면서 블록 사이즈가 유동적으로 바뀌기 때문이다. 전체 코드는 다음과 같다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3D 이미지 캐러셀</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="scene">
        <div class="carousel">
            <div class="item">1</div>
            <div class="item">2</div>
            <div class="item">3</div>
            <div class="item">4</div>
            <div class="item">5</div>
            <div class="item">6</div>
            <div class="item">7</div>
            <div class="item">8</div>
            <div class="item">9</div>
        </div>
    </div>
</body>
</html>
*{
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}


.scene{
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    perspective: 1200px;
}

.carousel{
    width: 220px;
    height: 150px;
    position: relative;
    transform-style: preserve-3d;
    animation: spin 5s infinite linear;
}

.item{
    position: absolute;
    top: 0;
    left: 0;
    width: 200px;
    height: 150px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px  solid black;
    color:#fff;
    font-size: 32px;
    font-weight: 600;
}

.item:nth-child(1){
    background-color: #ff7979;
    transform: rotateY(0deg) translateZ(288px);
}

.item:nth-child(2){
    background-color: #ffbe76;
    transform: rotateY(40deg) translateZ(288px);
}

.item:nth-child(3){
    background-color:#f0932b;
    transform: rotateY(80deg) translateZ(288px);
}

.item:nth-child(4){
    background-color:#7ed6df;
    transform: rotateY(120deg) translateZ(288px);
}

.item:nth-child(5){
    background-color:#e056fd;
    transform: rotateY(160deg) translateZ(288px);
}

.item:nth-child(6){
    background-color: #22a6b3;
    transform: rotateY(200deg) translateZ(288px);
}

.item:nth-child(7){
    background-color: #be2edd;
    transform: rotateY(240deg) translateZ(288px);
}

.item:nth-child(8){
    background-color:#4834d4;
    transform: rotateY(280deg) translateZ(288px);
}

.item:nth-child(9){
    background-color:#30336b;
    transform: rotateY(320deg) translateZ(288px);
}

@keyframes spin{
    from{
        transform: rotateY(0deg);
    }
    to{
        transform: rotateY(360deg);
    }
}

참고자료

  • CSS 3D 두 번째 시간 - 3D 캐러셀 만들기, 1분 코딩(유튜버)