코드스피츠 css rendering 4회차 part2 (step 44)

KHW·2021년 7월 5일
1

js-study

목록 보기
35/39
post-custom-banner

라디안(radian) / 디그리(degree)

라디안 : 호의 길이가 반지름과 같게 되는 만큼의 각
디그리 : 일상에서 사용하는 각도


공식

180 degree = (π * radian)
radian = 57.295....


라디안을 사용하는 이유

부채꼴 도형에서 반지름, 중심각, 호의 길이 3가지 중에 2가지만 알면 다른 한가지는 바로 쉽게 구할 수 있다.


CSS SPRITE

여러 개의 이미지를 하나의 이미지로 합쳐서 관리하는 이미지
(3D에서는 아틀라스라고도 불린다)


사용하는 이유

사용된 이미지가 많을 경우 웹 브라우저는 서버에 해당 이미지의 수만큼 요청해야만 하므로 웹 페이지의 로딩 시간이 오래 걸리게 된다.


목표 : 회전하는 원기둥 만들기

El 클래스 코드

	const El = class{
        	constructor(){this.el = document.createElement('div')}
        	set class(v){this.el.className = v;}
        }

let el = new El(); el.class = '클래스이름' 을 적용하면
해당 클래스를 적용시킨다.


Face 클래스 코드

const Face = class extends El{
        constructor(w,h,x,y,z,rx,ry,rz,tx,ty){
            super();
            this.el.style.cssText = `
                position:absolute;
                width:${w}px; height:${h}px;
                margin:-${h/2}px 0 0 -${w/2}px;
                transform:translate3d(${x}px,${y}px,${z}px)
                rotateX({rx}rad) rotateY(${ry}rad) rotateZ(${rz}rad);
                background-position: -${tx}px ${ty}px;
            `
        }
    }

Mesh 클래스 코드

const Mesh = class extends El {
  constructor(l, t) {
    super();
    this.el.style.cssText = `
      position: absolute;
      left: ${l}; top: ${t};
      transform-style: preserve-3d;
    `;
  }

  add(face) {
    if (!(face instanceof Face)) throw "invalid face";
    this.el.appendChild(face.el);
    return face;
  }
};

Face 클래스에서의 결과를 합쳐주는 역할


전체코드

<!DOCTYPE html>
<html lang="en">

<head>
    <style>
  @keyframes spin {
    to {
      transform: rotateY(360deg) rotateZ(360deg) rotateX(720deg);
    }
  }
  html,
  body {
    height: 100%;
  }
  body {
    perspective: 600px;
    background: #404040;
  }
  .ani {
    animation: spin 4s linear infinite;
  }
  .drum {
    background: url("http://keithclark.co.uk/labs/css-fps/drum2.png");
  }
</style>
</head>
<body>
    <div></div>
</body>    

<script>
    // 본격적으로 드럼통을 만들어보자

const El = class {
  constructor() {
    this.el = document.createElement("div");
  }
  set class(v) {
    this.el.className = v;
  }
};

// El을 상속받는 Face 클래스
const Face = class extends El {
  constructor(w, h, x, y, z, rx, ry, rz, tx, ty) {
    super();
    this.el.style.cssText = `
      position: absolute;
      width: ${w}px;
      height: ${h}px;
      margin: -${h / 2}px 0 0 -${w / 2}px;
      transform: translate3d(${x}px, ${y}px, ${z}px)
        rotateX(${rx}rad) rotateY(${ry}rad) rotateZ(${rz}rad);
      background-position: -${tx}px ${ty}px;
      backface-visibility: hidden; //⭐
    `;
  }
};

const Mesh = class extends El {
  constructor(l, t) {
    super();
    this.el.style.cssText = `
      position: absolute;
      left: ${l}; top: ${t};
      transform-style: preserve-3d;
    `;
  }

  add(face) {
    if (!(face instanceof Face)) throw "invalid face";
    this.el.appendChild(face.el);
    return face;
  }
};

const mesh = new Mesh("50%", "50%");

const r = 100,
  height = 196,
  sides = 20;
const sideAngle = (Math.PI / sides) * 2;
const sideLen = r * Math.tan(Math.PI / sides);

for (let c = 0; c < sides; c++) {
  const x = (Math.sin(sideAngle * c) * r) / 2;
  const z = (Math.cos(sideAngle * c) * r) / 2;
  const ry = Math.atan2(x, z);
  const face = new Face(sideLen + 1, height, x, 0, z, 0, ry, 0, sideLen * c, 0);
  face.class = "drum";
  mesh.add(face);
}

const tface = new Face(100, 100, 0, -98, 0, Math.PI / 2, 0, 0, 0, 100);
const bface = new Face(100, 100, 0, 98, 0, -Math.PI / 2, 0, 0, 0, 100);
tface.class = "drum";
bface.class = "drum";
mesh.add(tface);
mesh.add(bface);
mesh.class = "ani";
document.body.appendChild(mesh.el);

</script>
</html>

코드 수정하며 다시 고민해보기

1. 왜 bface의를 Math.PI가 아닌 -Math.PI를 줄까?

이유 : 만약 Math.PI로 부여한다면 마치 한쪽은 열려있는 것으로 보이나 실제로는 둘 다 막혀 있다.
단지, backface-visibility: hidden;에 의해 우리가 보는 구멍이 안보이는 상태이기 때문이다.

  • 한마디로 우리가 만들때 생성되는 위치가 둘 다 Math.PI로 진행할 경우 기존에 원기둥 옆면처럼 옆면을 바라보는 면에서 rotate를 같은 방향으로 줄 경우 같은 방향으로만 그림이 적용되기 때문에 위아래가 서로 다른방향을 줘야하는 서로다른 양수와 음수의 Math.PI를 부여해야한다.

2. 왜 tface,bface의 ty는 100을 부여할까

일단 사진 기준으로 봤을때 right는 +, top은 +이다.
이를 기준으로 ty가 100이라는 것은 위로 100만큼 위치한 부분을 기준을 잡는다는 것이다.

기존 사진에서 위로 100만큼 가면 다시 사진의 원통의 시작부분이기 때문에 ty를 100으로 잡았다.

정리하자면 ty를 -196으로 부여해도 같은 결과가 나온다.
왜냐하면 위로 100 올린것은 다른의미로 직사각형 형태부분인 196을 넘어서 원형형태부분의 시작점과 같기 때문이다.


정리

w,h : 사진부분의 높이 넓이 => 이를 추후에 중앙을 맞춘다.
x,y,z : 만들어진 부분에서부터 떨어진 거리 => 모아진 형태들을 넓게 퍼트릴 수 있다.
rx,ry,rz : 만들어진 것들의 회전 => 만들어진 것의 회전을 부여하여 원하는 회전 결과를 만들어낸다.
tx,ty : 2차원 사진을 기준으로 점이 시작하는 위치 => 2차원이므로 top, right가 +가 된다.


출처

라디안/디그리
코드

profile
나의 하루를 가능한 기억하고 즐기고 후회하지말자
post-custom-banner

0개의 댓글