111일차(1)/CSS(10) : 3차원 컨텐츠 만들기(3)
- 3d transform을 하려면 먼저 3차원 공간을 정의해야 한다.
- 그러고 나서 이 안에서 3차원 transform을 만든다.
- perspective (물체와 관찰자와의 거리), perspective-origin (관찰자의 위치 설정) 설정을 한다.
- 어떤 물건을 어디에서 바라보느냐에 따라 관점은 달라질 수 있다.
- 이 3차원 공간 안에서 3d transform을 하겠다고 선언하면 된다.
- 선언하는 방법은 transform-style 과 transform-origin 을 설정하면 된다.
- 이 파란 박스가 3차원 공간이다. 이 안에서 어떤 아이템을 3차원 transform하겠다!
- 지정한 개체를 rotateX(45deg) 한 상태이다. x축을 기준으로 45도 회전.
- 이 x축을 정면으로 바라본다고 하면 이 축은 . 모양으로 보일 것이다.
- 축을 정면으로 보았을 때 시계방향으로 45도 회전한 것(양수). 반시계방향은 - (음수)로 작성해주면 된다.
- 지정한 값이 양수냐 음수냐에 따라서 회전방향이 달라진다.
- y 축도 이와같다. 바라보는 위치에서 시계방향으로 움직이게 하기
- 이렇게 z축을 정면에서 바라보고 있는 형태이다.
- 이 xyz축이 만나는 지점도 우리가 결정할 수 있다. 이것이 transform-origin 이다.
- transform-origin: 50% 50%; 가 의미하는 값이 이것이다!
- xyz축이 교차하는 지점을 개체의 정가운데로 두겠다는 의미가 된다.
- 75% 로 지정해서 보면 3/4 지점 정도에 y축이 있다.
- 일반적으로 설정하는 값은 50%이다.
- 똑같이 transform 했지만 perspective-origin을 20% 20%로 지정해서 바라보면 이렇게 보인다.
- 관찰자가 물체를 지켜보는 위치!! 시선의 위치에 따라 보이는 모양이 달라진다.
- 이 시점도 일반적으로 설정하는 값은 50%이다.
* 카드 뒤집기 만들기
- div만들기! 가로/세로/높이를 정해서 만든 2개의 div를 일단 겹친 후, 하나를 뒤집을 것이다.
(원래는 왼쪽 이미지처럼 쌓이지만 css를 사용하면 도형을 겹칠 수 있다)
- 특정 버튼을 누르면 이것을 180도로 돌려서 뒤집은 div가 똑바로 보이도록 할 예정!
- 그러면 카드 2장을 겹쳐놓고 카드의 앞뒷면을 뒤집는 것처럼 보인다.
Step05_3dCardFlip.html
<!DOCTYPE html>
<html lang="en">
<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>Step05_3dCardFlip.html</title>
<style>
.wrapper{
perspective: 500%;
perspective-origin: 50% 50%;
width: 180px;
height: 200px;
}
.target{
transform-style: preserve-3d;
transform-origin: 50% 50%;
transition: transform 0.4s ease-out;
}
.target > div{
position: absolute;
top: 0;
left: 0;
width: 180px;
height: 200px;
backface-visibility: hidden;
/* 글자를 div의 가운데 오도록 */
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
font-weight: bold;
color: white;
}
.front{
background-color: orangered;
}
.back{
background-color: cadetblue;
transform: rotateY(180deg);
}
</style>
</head>
<body>
<div class="container">
<h3>카드 Flip 예제</h3>
<div class="wrapper">
<div class="target" id="myCard">
<div class="front">front</div>
<div class="back">back</div>
</div>
</div>
<button id="flipBtn">뒤집기</button>
</div>
<!-- jquery 로딩 -->
<script src="https://code.jquery.com/jquery-3.6.4.js"
integrity="sha256-a9jBBRygX1Bh5lt8GZjXDzyOB+bWve9EiO7tROUtj/E="
crossorigin="anonymous"></script>
<script>
//y축 회전값을 관리할 변수를 만들고 초기값 0 대입
let rY=0;
$("#flipBtn").on("click", ()=>{
rY += 180;
$("#myCard").css("transform", "rotateY("+rY+"deg)");
});
</script>
</body>
</html>
.target > div{
width: 200px;
height: 200px;
}
- target 안에 있는 div에 적용!
- 겹치는 방법 position absolute 를 적용하면 이렇게 겹쳐져서 하나인 것처럼 보인다.
- front와 back이 겹쳐진 모양!
.back{
border: 1px solid blue;
transform: rotateY(180deg);
}
- back을 Y축 기준으로 180도 뒤집어놓기
- backface-visibility: hidden; 하면 뒷면이 보이지 않는다.(디폴트 값이 visible 이다)
- visible 상태는 투명한 유리에 글씨가 쓰여있는 것이라고 생각하면 된다.
- 부모 div를 뒤집으면 된다. 그럼 자식 div는 자연히 같이 따라온다.
- jquery로 작성. 클릭하면 부모div 를 180도 뒤집어준다.
- 이렇게 하면 클릭시 카드가 뒤집히게 된다.
- 단 이렇게 작성하면 한번만 가능하다.
- rotateY() 여기 들어가는 값은 0을 기준으로 절대적인 값을 가지는 것이다.
- 정상 위치로부터 180도를 회전시킨다는 것이지 180도를 계속 회전시킨다는 것이 아니다. 누적되는 값이 아니다!
- 변수를 만들어 클릭할 때마다 180도씩 추가되는 코드로 작성해준다.
- 클릭하면 inline CSS가 증가한다.(검사 창에서 확인가능!)
- if문으로 분기해서 0이면 180으로, 180이면 0으로 바꾸도록 작성해볼 수도 있다.
- 글자를 좌우 가운데로 오도록 지정하고 카드 색상을 지정해주면 더 카드를 뒤집는 효과처럼 보인다.
- 최종 결과물!
- 페이지 로딩 시점에 필요한 컨텐츠를 배열해두고,
특정 시점에 타겟 안의 컨텐츠(target div)를 transform 시킨다.
- 특정 동작(버튼 클릭)을 하면 미리 배열된 상태를 유지하면서 움직인다.
배열되어 있는 자식 컨텐츠를 부모 컨텐츠를 사용해서 변화시키는 것이다.
* 회전하는 3D 큐브 만들기
- div 6개를 하나로 겹쳐놓고 시작해서, div를 하나하나 면에 맞춰 배치한다.
- 3d transform을 사용해서 최종적으로 큐브 형태로 만들 수 있도록!
- 만든 큐브 전체에 부모 div를 잡아두고 돌리면 큐브가 회전하도록 할 수도 있다.
- div가 겹쳐져있는데, 한 장을 뒤로 일정 양만큼 민다고 생각하기
- 그리고 90도 회전시키고 우측으로 밀기
- 이런 방식으로 5개를 배치할 예정!
- 뒷면은 밀고 나서 180도 회전시키면 된다.
- 각각의 div는 고유한 좌표계를 가지고 있다.
- 물체를 움직이거나 회전시키면 이 좌표계도 따라서 움직인다!
- 그러면 3번째 이미지의 회전시킨 div를 오른쪽으로 평행이동 시킨다고 하면? z축 방향으로 밀어야 한다.
Step06_3dCube.html
<!DOCTYPE html>
<html lang="en">
<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>Step06_3dCube.html</title>
<style>
.wrapper{
perspective: 500px;
perspective-origin: 50% 50%;
}
.cube{
width: 400px;
height: 400px;
margin: 0 auto;
transform-style: preserve-3d;
transform-origin: 50% 50%;
transform: translateZ(-200px);
}
.cube > div{
border: 2px solid palevioletred;
position: absolute;
top:0;
left:0;
width: 400px;
height: 400px;
background-color: antiquewhite;
display: flex;
justify-content: center;
align-items: center;
font-size: 100px;
font-weight: bold;
opacity: 0.5;
}
.cube > div:nth-child(1){
transform: translateZ(200px);
}
.cube > div:nth-child(2){
transform: rotateY(90deg) translateZ(200px);
}
.cube > div:nth-child(3){
transform: rotateY(180deg) translateZ(200px);
}
.cube > div:nth-child(4){
transform: rotateY(270deg) translateZ(200px);
}
.cube > div:nth-child(5){
transform: rotateX(90deg) translateZ(200px);
}
.cube > div:nth-child(6){
transform: rotateX(-90deg) translateZ(200px);
}
/* .cube{
transition: transform 0.4s ease-out;
}
.cube:hover{
transform: translateZ(-200px) rotateX(45deg) rotateY(90deg);
} */
@keyframes rotateAni{
0%{
transform: translateZ(-200px) rotateX(0deg) rotateY(0deg);
}
100%{
transform: translateZ(-200px) rotateX(360deg) rotateY(360deg);
}
}
.cube:hover{
animation: rotateAni 5s infinite linear alternate;
}
</style>
</head>
<body>
<div class="container">
<h3>3d cube 테스트</h3>
<div class="wrapper">
<div class="cube">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</div>
</div>
</div>
</body>
</html>
- 이렇게 작성해서 tab으로 자동완성시키면 아래와 같이 작성된다. Emmet을 잘 활용하기
- 3차원 공간으로 만들 div 안에 div 6개를 만들어준다.
- cube의 자식 div에 적용할 css !
- 6개 div를 겹쳐놓고 하나씩 움직이게 할 것
.cube > div:nth-child(1)
- 자식 div 중 첫번째 것을 가리킨다!
- 사이즈가 너무 커져서 cube 를 -200px 만큼 뒤로 밀어주었다.
.cube > div:nth-child(2){
transform: rotateY(90deg) translateZ(200px);
}
- 2번째 div를 회전시켜서 밀었다.어버린것(오른쪽 면)
.cube > div:nth-child(1){
transform: translateZ(200px);
}
.cube > div:nth-child(2){
transform: rotateY(90deg) translateZ(200px);
}
.cube > div:nth-child(3){
transform: rotateY(180deg) translateZ(200px);
}
.cube > div:nth-child(4){
transform: rotateY(270deg) translateZ(200px);
}
.cube > div:nth-child(5){
transform: rotateX(90deg) translateZ(200px);
}
.cube > div:nth-child(6){
transform: rotateX(-90deg) translateZ(200px);
}
- 같은 방식으로 전체를 적용하면 이런 도형이 된다.
- 1번 면은 앞으로 밀기 적용
.cube{
transition: transform 0.4s ease-out;
}
.cube:hover{
transform: translateZ(-200px) rotateX(45deg);
}
- 마우스를 올렸을 때 X축을 기준으로 45도 회전시키면 이렇게 보인다.
- @keyframes 를 사용해서 큐브에 애니메이션 적용하기
- 큐브가 무한히 회전하는 애니메이션으로 만들 수 있다.
- 5s alternate 로 지정했기 때문에 5초 이후에는 반대방향으로 진행된다.
- 0%와 100%를 왔다갔다 하게 된다.
* 클릭할 때마다 큐브 좌우로 회전시키기
Step06_example.html
<!DOCTYPE html>
<html lang="en">
<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>Step06_example.html</title>
<style>
.wrapper{
perspective: 500px;
perspective-origin: 50% 0%;
height: 600px;
border: 1px solid blue;
padding-top: 100px;
box-sizing: border-box; /* padding과 border를 width, height에 포함되도록 */
}
.cube{
width: 400px;
height: 400px;
margin: 0 auto;
transform-style: preserve-3d;
transform-origin: 50% 50%;
transform: translateZ(-200px);
}
.cube > div{
border: 2px solid palevioletred;
position: absolute;
top:0;
left:0;
width: 400px;
height: 400px;
background-color: antiquewhite;
display: flex;
justify-content: center;
align-items: center;
font-size: 100px;
font-weight: bold;
opacity: 0.5;
}
.cube > div:nth-child(1){
transform: translateZ(200px);
}
.cube > div:nth-child(2){
transform: rotateY(90deg) translateZ(200px);
}
.cube > div:nth-child(3){
transform: rotateY(180deg) translateZ(200px);
}
.cube > div:nth-child(4){
transform: rotateY(270deg) translateZ(200px);
}
.cube{
transition: transform 0.4s ease-out;
}
nav{
text-align: center;
}
nav button{
font-size: 40px;
}
</style>
</head>
<body>
<div class="container">
<h3>3d cube 테스트</h3>
<div class="wrapper">
<div class="cube">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
</div>
</div>
<nav>
<button id="prevBtn">«</button>
<button id="nextBtn">»</button>
</nav>
</div>
<!-- jquery 로딩 -->
<script src="https://code.jquery.com/jquery-3.6.4.js"
integrity="sha256-a9jBBRygX1Bh5lt8GZjXDzyOB+bWve9EiO7tROUtj/E="
crossorigin="anonymous"></script>
<script>
//위의 버튼을 눌렀을때 .cube를 90도씩 y축 기준으로 회전하도록 해보세요
let rY=0;
$("#prevBtn").click(()=>{
rY -= 90;
$(".cube").css("transform", "translateZ(-200px) rotateY("+rY+"deg)");
})
$("#nextBtn").on("click", ()=>{
rY += 90;
$(".cube").css("transform", "translateZ(-200px) rotateY("+rY+"deg)");
})
</script>
</body>
</html>
- 이전 큐브 예제에서 그대로 복사해와서 div 4개만 남김
- 그러면 위, 아래는 뚫려있는 박스 형태가 된다.
- 버튼을 누르면 회전시킬 수 있도록 navbar에 좌,우 이동 버튼을 만들어준다.
- jquery에서 .on("click", xxx) 말고 바로 .click 을 사용해도 된다.
- 밀어놓고 회전을 시켜야하는데 밀어놓지 않았기 때문에 도형이 앞으로 튀어나온다.
- -200으로 배치해야 한다.
- 처음부터 위치값을 -200px로 조정해놓고 돌린다.
- 이제 화살표를 클릭하면 큐브를 한칸씩 좌/우로 빙글빙글 돌게 하는 효과를 낼 수 있다.
'국비교육(22-23)' 카테고리의 다른 글
113일차(1)/CSS(12) : 3차원 컨텐츠 만들기(5) / TouchSwipe 활용 (0) | 2023.03.23 |
---|---|
112일차(1)/CSS(11) : 3차원 컨텐츠 만들기(4) (1) | 2023.03.22 |
110일차(1)/CSS(9) : 3차원 컨텐츠 만들기(2) (1) | 2023.03.20 |
109일차(2)/CSS(8) : 3차원 컨텐츠 만들기(1) (0) | 2023.03.17 |
109일차(1)/Android App(73) : 모바일 갤러리 기능 구현(7) (0) | 2023.03.17 |