Play CSS 3D - regular octahedron and regular dodecahedron

Keywords: Front-end Attribute

Octahedron and dodecahedron, although the two regular polyhedrons have more combinations of faces, but because of the symmetry, only half of the structure needs to be made, and the other half can be connected by inversion.

Regular eight face

Orthooctahedron can be imagined as "two pyramids" overlapping together. In order to facilitate our subsequent rotation of the whole pyramid, we need to use another container to wrap the pyramid. We can imagine that the four sides of the pyramid can be transformed into a group, which can be transformed or moved. The structure of HTML is as follows: space contains box 1 and box 2, box 1. It's a pyramid in the upper half, and box 2 is a pyramid in the lower half.

<div class="camera">
    <div class="space">
        <div class="box1">
            <div class="face1"></div>
            <div class="face2"></div>
            <div class="face3"></div>
            <div class="face4"></div>
        </div>
        <div class="box2">
            <div class="face1"></div>
            <div class="face2"></div>
            <div class="face3"></div>
            <div class="face4"></div>
        </div>
    </div>
</div>

Again, set up camera and space first.

.camera{
    width:200px;
    height:200px;
    -webkit-perspective-origin:50% 50%;
    -webkit-perspective:500px;
}
.space{
    position:relative;
    width:100%;
    height:100%;
    border:1px dashed #000;
    -webkit-transform-style:preserve-3d;
}

Then because the face ts we use are triangles, we also need to use border to achieve, remember that position should be set to absolute, and because box1, box2 itself is also a three-dimensional space, so we also need to add the attribute of transform-style: preserve-3d.

.space div{
    position:absolute;
}
.box1, .box2{
    transform-style:preserve-3d;
}
.box1 div,.box2 div{
  width:0;
  height:0;
  border-width:0 50px 87px;
  border-style:solid;
  opacity:.4;
}

Then make the pyramid model of box 1. Because the angle between each face of octahedron is 109.28 degrees, and because it is divided into two halves, the difference between the middle and the half is 54.64 degrees, so we need to rotate the angle is 90 - 54.64 = 35.36, so we will rotate the angle of the main, first see face1, 35.36 degrees inward along the x axis.

.face1{
    border-color:transparent transparent #f00;
    transform-origin:center bottom;
    transform:translateX(50px) translateY(50px) rotateX(35.36deg);
}

face2 rotates 90 degrees around the Y axis and 35.36 degrees around the X axis.

.face2{
    border-color:transparent transparent #00f;
    transform-origin:right bottom;
    transform:translateX(50px) translateY(50px) rotateY(-90deg) rotateX(-35.36deg);
}

Face 3 is opposite Face 1, so first move 100px on the Z axis, then rotate 35.36 degrees around the X axis.

.face3{
    border-color:transparent transparent #0f0;
    transform-origin:left bottom;
    transform:translateX(50px) translateY(50px)  translateZ(-100px) rotateX(-35.36deg);
}

Face4 is the same as face2 except that face4 uses the left side as the center.

.face4{
    border-color:transparent transparent #f90;
    transform-origin:left bottom;
    transform:translateX(50px) translateY(50px) rotateY(90deg) rotateX(-35.36deg);
}

Basically, the pyramid model of the upper part of the box 1 has been completed. At this time, the box 1 and the box 2 overlap. As long as we invert the box 2 and change its position, we can become an octahedron model. But there will be an interesting problem. Where is the center of the box 2 deformation? At this time, we have to use several times of trigonometric function calculation, because it is the center point of a pyramid model rotation, so we have to inspect the Z axis. First of all, it is no problem to set the X axis as the center. Because the bottom of the pyramid is a square of 100 x 100, the position of the center point at 50 PX is also normal, but the Y axis is more troublesome. First, we can see the regular triangle. One side length is 100px, the length of the middle line is sin (60) x 100 = 86.6, then the height of the pyramid is 70.6 with sin (54.64) x 86.6, and 71 with rounding. So when we set the deformation center on this side, it will rotate around the top of the pyramid. After 180 degrees of rotation, we will use translateY to position and move about the distance. It's about 100 + 71/2 = 135, but since we've been rounding from the beginning, it's inevitable that there will be errors in integer representation (two pyramids can't be connected), so we have to use manual fine-tuning, which is set to - 132px.

.box2{
      transform-origin: center 71px -50px;
      transform: rotateX(180deg) translateY(-132px);
}

Similarly, rotating space makes the whole octahedron rotate and looks more stereoscopic.

.space{
    position:relative;
    width:100%;
    height:100%;
    -webkit-transform-style:preserve-3d;
    -webkit-transform-origin:center center -50px;
    -webkit-animation:s 4s linear infinite;
}
@-webkit-keyframes s{
    0%{
        -webkit-transform:rotateY(0);
    }
    100%{
        -webkit-transform:rotateY(-359.9deg);
    }
}

Regular dodecahedron

After making regular octahedron, the principle of regular dodecahedron is almost the same, but it is more complex because it is composed of twelve regular pentagons, but here we need to grow five faces from the five sides of the regular pentagon. The angle of each face is 116.56 degrees, 180 - 116.56 = 63.44. The angle to be used will probably not depart from these two values, of course, because of the fact that there are five sides of the regular pentagon. There are many decimal points, so you still have to fine-tune them manually (because the smallest unit of pixels is 1).

The structure of HTML is as follows. It is also divided into two parts, each with six aspects.

<div class="camera">
    <div class="space">
        <div class="box1">
            <div class="face1"></div>
            <div class="face2"></div>
            <div class="face3"></div>
            <div class="face4"></div>
            <div class="face5"></div>
            <div class="face6"></div>
        </div>
        <div class="box2">
            <div class="face1"></div>
            <div class="face2"></div>
            <div class="face3"></div>
            <div class="face4"></div>
            <div class="face5"></div>
            <div class="face6"></div>
        </div>
    </div>
</div>

Set the initial CSS first.

.camera{
    width:200px;
    height:200px;
    perspective-origin:50% 0%;
    -moz-perspective-origin:50% 0%;
    -webkit-perspective-origin:50% 0%;
    perspective:500px;
    -moz-perspective:500px;
    -webkit-perspective:500px;
}
.space{
    position:relative;
    width:100%;
    height:100%;
    border:1px dashed #000;
    transform-style:preserve-3d;
    -moz-transform-style:preserve-3d;
    -webkit-transform-style:preserve-3d;
}
.space div{
    position:absolute;
}
.box1, .box2{
    transform-style:preserve-3d;
    -moz-transform-style:preserve-3d;
    -webkit-transform-style:preserve-3d;
}

Then slowly draw every face. First, draw all the regular pentagons.

.box1 div,.box2 div{
  width:162px;
  height:154px;
  opacity:.9;
}
.box1 div:before,.box2 div:before{
  position:absolute;
  content:"";
  top:0;
  width:0;
  height:0;
  border-width:0 81px 59px;
  border-style:solid;
  border-color:transparent transparent #069;
}
.box1 div:after,.box2 div:after{
  position:absolute;
  content:"";
  top:59px;
  left:0;
  width:100px;
  height:0;
  background:none;
  border-width:95px 31px 0;
  border-style:solid;   
  border-color:#069 transparent transparent;
}

Because it is from the five sides of the Pentagon to the five sides of the outside, so face1 will not change, then let box do rotation, and face2 to face6 these five sides, the simpler way is to do Z axis rotation first, then Y axis rotation, then translate each side to the corresponding position, but here we have to pay attention to, because we have done Z axis and Y axis rotation first. The axis rotates, so the coordinate system of each side has changed. You can see how to translate by referring to the following figure. Basically, after the Y axis rotates to - 116.56 degrees, each side moves 69px towards its own Y axis. Then, in order to keep the edges together, it must move 31px (cos (180-116.56) x 69) to the Y axis and 62px (sin (180-116.56) x 69 to the Z axis. )

So face2 to face6 can be written almost exactly the same way (Z axis rotation angle 72 degrees per surface difference)

.face2{  
    transform-origin:81px 85px 0;
        transform:rotateZ(0) rotateX(-116.56deg) translateY(-69px) translateY(-31px) translateZ(62px);
}
.face3{  
        transform-origin:81px 85px 0;
        transform:rotateZ(72deg) rotateX(-116.56deg) translateY(-69px) translateY(-31px) translateZ(62px);
}
.face3{  
        transform-origin:81px 85px 0;
        transform:rotateZ(72deg) rotateX(-116.56deg) translateY(-69px) translateY(-31px) translateZ(62px);
}
.face4{
        transform-origin:81px 85px 0;
        transform:rotateZ(144deg) rotateX(-116.56deg) translateY(-69px) translateY(-31px) translateZ(62px);
}
.face5{  
      transform-origin:81px 85px 0;
      transform:rotateZ(-144deg) rotateX(-116.56deg) translateY(-69px) translateY(-31px) translateZ(62px);
}
.face6{  
        transform-origin:81px 85px 0;
      transform:rotateZ(-72deg) rotateX(-116.56deg) translateY(-69px) translateY(-31px) translateZ(62px);
}

In order to make each surface different in color, the border color of pseudo-elements must be changed here.

.box1 .face2:before{
  border-color:transparent transparent #f00;
}
.box1 .face2:after{
  border-color:#f00 transparent transparent;
}
.box1 .face3:before{
  border-color:transparent transparent #0f0;
}
.box1 .face3:after{
  border-color:#0f0 transparent transparent;
}
.box1 .face4:before{
  border-color:transparent transparent #f90;
}
.box1 .face4:after{
  border-color:#f90 transparent transparent;
}
.box1 .face5:before{
  border-color:transparent transparent #09f;
}
.box1 .face5:after{
  border-color:#09f transparent transparent;
}
.box1 .face6:before{
  border-color:transparent transparent #f0f;
}
.box1 .face6:after{
  border-color:#f0f transparent transparent;
}

Finally, for the rotation of box 1 and box 2, we should pay more attention to translateZ. The height of the Pentagon is 276 (sin (63.44) x 154 x 2), but the height of the short side of the joint must be deducted, so it will become 223 (276 - sin (36) x 100).

.box1{
    transform-origin:81px 85px 0;
    transform:rotateX(90deg) translateZ(-223px);
}
.box2{
    transform-origin:81px 85px 0;
    transform:rotateX(-90deg);
}

space with animation effect, to verify whether each side has a perfect joint.

.space{
    position:relative;
    width:100%;
    height:100%;
    -webkit-transform-style:preserve-3d;
    -webkit-transform-origin:81px 170px 0;
    -webkit-animation:s 4s linear infinite;
}
@-webkit-keyframes s{
    0%{
        -webkit-transform:rotateY(0) rotateX(0);
    }
    100%{
        -webkit-transform:rotateY(-359.9deg)  rotateX(359.9deg);
    }
}


Posted by HeyRay2 on Sat, 11 May 2019 06:31:55 -0700