みかづきブログ その3

3ヶ月つづけてみました。

CSSで三角柱をまわそう。

今回は、CSSをつかって三角柱をつくり、それをくるくると回してみます。

こんな感じです。



では、ざっくりとですが、HTML、CSSの解説を。

HTML

<div class="wrapper">
    <div class="surface s0"></div>
    <div class="surface s1"></div>
    <div class="surface s2"></div>
</div>

非常にシンプルです。
三角柱なので面を3つ用意して、管理しやすくするためにそれらを1つの要素でラップしておきます。

CSS

* {
  margin: 0; padding: 0;
  border: 0;
}

html {
    background: #eee;
}

.wrapper {
  position: absolute;
  top: 50%; left: 50%;
  -webkit-transform-style: preserve-3d;
  -webkit-transform-origin: 0 0;
  -webkit-animation: "box3d" 10s infinite linear;
  -moz-transform-style: preserve-3d;
  -moz-transform-origin: 0 0;
  -moz-animation: "box3d" 10s infinite linear;
  -ms-transform-style: preserve-3d;
  -ms-transform-origin: 0 0;
  -ms-animation: "box3d" 10s infinite linear;
  -o-transform-style: preserve-3d;
  -o-transform-origin: 0 0;
  -o-animation: "box3d" 10s infinite linear;
  transform-style: preserve-3d;
  transform-origin: 0 0;
  animation: "box3d" 10s infinite linear;
}

.surface {
  position: absolute;
  width: 330px; height: 80px;
  -webkit-transform-origin: 50% 50%;
  -webkit-transform-style: preserve-3d;
  -moz-transform-origin: 50% 50%;
  -moz-transform-style: preserve-3d;
  -ms-transform-origin: 50% 50%;
  -ms-transform-style: preserve-3d;
  -o-transform-origin: 50% 50%;
  -o-transform-style: preserve-3d;
  transform-origin: 50% 50%;
  transform-style: preserve-3d;
}

.surface.s0 {
  top: -5px;
  background: #c80000;
  background: rgba(200, 0, 0, .8);
  -webkit-transform: translateX(-165px) translateY(-40px) rotateX(0deg) translateZ(23.09px);
  -moz-transform: translateX(-165px) translateY(-40px) rotateX(0deg) translateZ(23.09px);
  -ms-transform: translateX(-165px) translateY(-40px) rotateX(0deg) translateZ(23.09px);
  -o-transform: translateX(-165px) translateY(-40px) rotateX(0deg) translateZ(23.09px);
  transform: translateX(-165px) translateY(-40px) rotateX(0deg) translateZ(23.09px);
}

.surface.s1 {
  top: -5px;
  background: #00c800;
  background: rgba(0, 200, 0, .8);
  -webkit-transform: translateX(-165px) translateY(-40px) rotateX(60deg) translateZ(-23.09px) rotateX(180deg);
  -moz-transform: translateX(-165px) translateY(-40px) rotateX(60deg) translateZ(-23.09px) rotateX(180deg);
  -ms-transform: translateX(-165px) translateY(-40px) rotateX(60deg) translateZ(-23.09px) rotateX(180deg);
  -o-transform: translateX(-165px) translateY(-40px) rotateX(60deg) translateZ(-23.09px) rotateX(180deg);
  transform: translateX(-165px) translateY(-40px) rotateX(60deg) translateZ(-23.09px) rotateX(180deg);
}

.surface.s2 {
  top: -5px;
  background: #0000c8;
  background: rgba(0, 0, 200, .8);
  -webkit-transform: translateX(-165px) translateY(-40px) rotateX(120deg) translateZ(23.09px);
  -moz-transform: translateX(-165px) translateY(-40px) rotateX(120deg) translateZ(23.09px);
  -ms-transform: translateX(-165px) translateY(-40px) rotateX(120deg) translateZ(23.09px);
  -o-transform: translateX(-165px) translateY(-40px) rotateX(120deg) translateZ(23.09px);
  transform: translateX(-165px) translateY(-40px) rotateX(120deg) translateZ(23.09px);
}

@-webkit-keyframes box3d {
  0% {
    -webkit-transform: rotateX(0deg);
  }

  30% {
    -webkit-transform: rotateX(0deg);
  }

  33.33% {
    -webkit-transform: rotateX(-120deg);
  }

  63.33% {
    -webkit-transform: rotateX(-120deg);
  }

  66.66% {
    -webkit-transform: rotateX(-240deg);
  }

  96.66% {
    -webkit-transform: rotateX(-240deg);
  }

  100% {
    -webkit-transform: rotateX(-360deg);
  }
}

@-moz-keyframes box3d {
  0% {
    -moz-transform: rotateX(0deg);
  }

  30% {
    -moz-transform: rotateX(0deg);
  }

  33.33% {
    -moz-transform: rotateX(-120deg);
  }

  63.33% {
    -moz-transform: rotateX(-120deg);
  }

  66.66% {
    -moz-transform: rotateX(-240deg);
  }

  96.66% {
    -moz-transform: rotateX(-240deg);
  }

  100% {
    -moz-transform: rotateX(-360deg);
  }
}

@-ms-keyframes box3d {
  0% {
    -ms-transform: rotateX(0deg);
  }

  30% {
    -ms-transform: rotateX(0deg);
  }

  33.33% {
    -ms-transform: rotateX(-120deg);
  }

  63.33% {
    -ms-transform: rotateX(-120deg);
  }

  66.66% {
    -ms-transform: rotateX(-240deg);
  }

  96.66% {
    -ms-transform: rotateX(-240deg);
  }

  100% {
    -ms-transform: rotateX(-360deg);
  }
}

@-o-keyframes box3d {
  0% {
    -o-transform: rotateX(0deg);
  }

  30% {
    -o-transform: rotateX(0deg);
  }

  33.33% {
    -o-transform: rotateX(-120deg);
  }

  63.33% {
    -o-transform: rotateX(-120deg);
  }

  66.66% {
    -o-transform: rotateX(-240deg);
  }

  96.66% {
    -o-transform: rotateX(-240deg);
  }

  100% {
    -o-transform: rotateX(-360deg);
  }
}

@keyframes box3d {
  0% {
    transform: rotateX(0deg);
  }

  30% {
    transform: rotateX(0deg);
  }

  33.33% {
    transform: rotateX(-120deg);
  }

  63.33% {
    transform: rotateX(-120deg);
  }

  66.66% {
    transform: rotateX(-240deg);
  }

  96.66% {
    transform: rotateX(-240deg);
  }

  100% {
    transform: rotateX(-360deg);
  }
}

長いです。非常に長いです。
これは多くのブラウザに対応するためにベンダープレフィックスをつけているから長くなっています。

ポイントとしては、

  1. wrapperの変形基準点を左上にする。
  2. surfaceの変形基準点を中心にする。
  3. wrapperの変形基準点とsurfaceの変形基準点を重ねる。(surfaceのx座標、y座標をそれぞれ高さの半分、幅の半分だけ移動させる)
  4. surfaceを60度ずつ回転させる(正三角形なので)
  5. surfaceを三角形の重心の分だけ押し出す。(1辺の√3/6倍)

といった感じでしょうか。
非常に言語化しにくいので、コードを見てもらったほうが早いかもしれません。