【喵猫秀秀秀】用CSS向你展示猫立方!!

2,042 阅读2分钟

一起用代码吸猫!本文正在参与【喵星人征文活动】

前言

这次,我们用vue2+scss,带大家来实现一个六面体的猫立方。

本次的逻辑我们不适用任何的js代码,仅仅只依靠css来完成。

所以,通过本片文章,你可以收获一些css动画相关的技巧。

先看看效果

cat3D.gif

预习

本次我们要用到的知识点

  1. transform 解释:transform 属性向元素应用 2D 或 3D 转换。该属性允许我们对元素进行旋转、缩放、移动或倾斜。

要用哪个,可以对着这个表格查

image.png

  1. transform-style 解释:transform--style属性指定嵌套元素是怎样在三维空间中呈现。

注意:  使用此属性必须先使用 transform 属性.

  1. transition 解释:transition 属性是一个简写属性,用于设置四个过渡属性:
  • transition-property
  • transition-duration
  • transition-timing-function
  • transition-delay

注释:请始终设置 transition-duration 属性,否则时长为 0,就不会产生过渡效果。

分析

我们先拆解下这个猫3D的特点,它有以下特点

  1. 它一直在不停的转
  2. 它由两个六面体组成,外面一个,里面一个
  3. 鼠标靠近外面的六面体,六面体的六个面会往外扩,露出里面的小六面体

开始

1.因为我们做的是六面体,有2个六面体,一个在里面,一个在外面。2个六面体,12个面,先准备12张猫主子的图片。

image.png

  1. 然后我们新建img3D.vue文件,开干

image.png

步骤一

先来完成第一个特点不停的转

cat3D1.gif 代码如下:

<template>
  <div>
    <div class="container">
    </div>
  </div>
</template>

<script>

</script>

<style lang="scss" scoped>
* {
  margin: 0px;
  padding: 0px;
}

.container {
  position: relative;
  margin: 0px auto;
  margin-top: 9%;
  margin-left: 42%;
  width: 200px;
  height: 200px;
  transform: rotateX(-30deg) rotateY(-80deg);
  transform-style: preserve-3d;
  animation: rotate 15s infinite;
  /* 我这里用一个边框线来更容易看到效果 */
  border: 1px solid red;
}

/* 旋转立方体 */
@keyframes rotate {
  from {
    transform: rotateX(0deg) rotateY(0deg);
  }

  to {
    transform: rotateX(360deg) rotateY(360deg);
  }
}
</style>

步骤二

弄外面的六面体,并且六面体在鼠标悬停的时候,需要往外扩 效果如下:

cat3D2.gif

<template>
  <div>
    <div class="container">
      <!-- 外层立方体 -->
      <div class="outer-container">
        <div class="outer-top">
          <img :src="cat1" />
        </div>
        <div class="outer-bottom">
          <img :src="cat2" />
        </div>
        <div class="outer-front">
          <img :src="cat3" />
        </div>
        <div class="outer-back">
          <img :src="cat4" />
        </div>
        <div class="outer-left">
          <img :src="cat5" />
        </div>
        <div class="outer-right">
          <img :src="cat6" />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import cat1 from "@/assets/cats/cat1.png";
import cat2 from "@/assets/cats/cat2.png";
import cat3 from "@/assets/cats/cat3.png";
import cat4 from "@/assets/cats/cat4.png";
import cat5 from "@/assets/cats/cat5.png";
import cat6 from "@/assets/cats/cat6.png";

export default {
  data() {
    return {
      cat1,
      cat2,
      cat3,
      cat4,
      cat5,
      cat6,
    };
  },
};
</script>

<style lang="scss" scoped>
...
/* 设置图片可以在三维空间里展示 */
.container .outer-container {
  transform-style: preserve-3d;
}
/* 设置图片尺寸固定宽高200px */
.outer-container img {
  width: 200px;
  height: 200px;
}

/* 外层立方体样式 */
.outer-container .outer-top,
.outer-container .outer-bottom,
.outer-container .outer-right,
.outer-container .outer-left,
.outer-container .outer-front,
.outer-container .outer-back {
  position: absolute;
  top: 0;
  left: 0;
  width: 200px;
  height: 200px;
  border: 1px solid #fff;
  opacity: 0.3;
  transition: all 0.9s;
}

/* 全靠transform 属性撑起来了外面的六面体 */
.outer-top {
  transform: rotateX(90deg) translateZ(100px);
}

.outer-bottom {
  transform: rotateX(-90deg) translateZ(100px);
}

.outer-front {
  transform: rotateY(0deg) translateZ(100px);
}

.outer-back {
  transform: translateZ(-100px) rotateY(180deg);
}

.outer-left {
  transform: rotateY(90deg) translateZ(100px);
}

.outer-right {
  transform: rotateY(-90deg) translateZ(100px);
}

/* 鼠标悬停 外面的六面体,六条边都往外扩出去,并且透明度变浅了,猫猫图片更清晰了 */
.cube:hover .outer-top {
  right: -70px;
  bottom: -70px;
  opacity: 0.8;
  transform: rotateX(90deg) translateZ(200px);
}

.container:hover .outer-bottom {
  right: -70px;
  bottom: -70px;
  opacity: 0.8;
  transform: rotateX(-90deg) translateZ(200px);
}

.container:hover .outer-front {
  right: -70px;
  bottom: -70px;
  opacity: 0.8;
  transform: rotateY(0deg) translateZ(200px);
}

.container:hover .outer-back {
  right: -70px;
  bottom: -70px;
  opacity: 0.8;
  transform: translateZ(-200px) rotateY(180deg);
}

.container:hover .outer-left {
  right: -70px;
  bottom: -70px;
  opacity: 0.8;
  transform: rotateY(90deg) translateZ(200px);
}

.container:hover .outer-right {
  right: -70px;
  bottom: -70px;
  opacity: 0.8;
  transform: rotateY(-90deg) translateZ(200px);
}
</style>

步骤三

弄里面的六面体,这个六边形比较简单,没有移入移出,鼠标悬停等的样式效果 效果如下:

cat3D.gif 代码如下:

<template>
  <div>
    <div class="container">
      <!-- 外层立方体 -->
      ...
      <!-- 内层立方体 -->
      <div class="inner-container">
        <div class="inner-top">
          <img :src="cat7" />
        </div>
        <div class="inner-bottom">
          <img :src="cat8" />
        </div>
        <div class="inner-front">
          <img :src="cat9" />
        </div>
        <div class="inner-back">
          <img :src="cat10" />
        </div>
        <div class="inner-left">
          <img :src="cat11" />
        </div>
        <div class="inner-right">
          <img :src="cat12" />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
...
import cat7 from "@/assets/cats/cat7.png";
import cat8 from "@/assets/cats/cat8.png";
import cat9 from "@/assets/cats/cat9.png";
import cat10 from "@/assets/cats/cat10.png";
import cat11 from "@/assets/cats/cat11.png";
import cat12 from "@/assets/cats/cat12.png";

export default {
  data() {
    return {
      ...
      cat7,
      cat8,
      cat9,
      cat10,
      cat11,
      cat12,
    };
  },
};
</script>

<style lang="scss" scoped>
...
/* 设置图片可以在三维空间里展示 */
.container .outer-container,
.container .inner-container {
  transform-style: preserve-3d;
}

...

/* 设置里面的六面体样式 */
/* 嵌套的内层立方体样式 */
.inner-container > div {
  position: absolute;
  top: 35px;
  left: 35px;
  width: 130px;
  height: 130px;
}
/* 里面的六面体尺寸宽高设置130px */
.inner-container img {
  width: 130px;
  height: 130px;
}

.inner-top {
  transform: rotateX(90deg) translateZ(65px);
}

.inner-bottom {
  transform: rotateX(-90deg) translateZ(65px);
}

.inner-front {
  transform: rotateY(0deg) translateZ(65px);
}

.inner-back {
  transform: translateZ(-65px) rotateY(180deg);
}

.inner-left {
  transform: rotateY(90deg) translateZ(65px);
}

.inner-right {
  transform: rotateY(-90deg) translateZ(65px);
}
</style>

最后完整代码:

<template>
  <div>
    <div class="container">
      <!-- 外层立方体 -->
      <div class="outer-container">
        <div class="outer-top">
          <img :src="cat1" />
        </div>
        <div class="outer-bottom">
          <img :src="cat2" />
        </div>
        <div class="outer-front">
          <img :src="cat3" />
        </div>
        <div class="outer-back">
          <img :src="cat4" />
        </div>
        <div class="outer-left">
          <img :src="cat5" />
        </div>
        <div class="outer-right">
          <img :src="cat6" />
        </div>
      </div>
      <!-- 内层立方体 -->
      <div class="inner-container">
        <div class="inner-top">
          <img :src="cat7" />
        </div>
        <div class="inner-bottom">
          <img :src="cat8" />
        </div>
        <div class="inner-front">
          <img :src="cat9" />
        </div>
        <div class="inner-back">
          <img :src="cat10" />
        </div>
        <div class="inner-left">
          <img :src="cat11" />
        </div>
        <div class="inner-right">
          <img :src="cat12" />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import cat1 from "@/assets/cats/cat1.png";
import cat2 from "@/assets/cats/cat2.png";
import cat3 from "@/assets/cats/cat3.png";
import cat4 from "@/assets/cats/cat4.png";
import cat5 from "@/assets/cats/cat5.png";
import cat6 from "@/assets/cats/cat6.png";
import cat7 from "@/assets/cats/cat7.png";
import cat8 from "@/assets/cats/cat8.png";
import cat9 from "@/assets/cats/cat9.png";
import cat10 from "@/assets/cats/cat10.png";
import cat11 from "@/assets/cats/cat11.png";
import cat12 from "@/assets/cats/cat12.png";

export default {
  data() {
    return {
      cat1,
      cat2,
      cat3,
      cat4,
      cat5,
      cat6,
      cat7,
      cat8,
      cat9,
      cat10,
      cat11,
      cat12,
    };
  },
};
</script>

<style lang="scss" scoped>
* {
  margin: 0px;
  padding: 0px;
}

.container {
  position: relative;
  margin: 0px auto;
  margin-top: 9%;
  margin-left: 42%;
  width: 200px;
  height: 200px;
  transform: rotateX(-30deg) rotateY(-80deg);
  transform-style: preserve-3d;
  animation: rotate 15s infinite;
  /* 我这里用一个边框线来更容易看到效果 */
  /* border: 1px solid red; */
}

/* 旋转立方体 */
@keyframes rotate {
  from {
    transform: rotateX(0deg) rotateY(0deg);
  }

  to {
    transform: rotateX(360deg) rotateY(360deg);
  }
}
/* 设置图片可以在三维空间里展示 */
.container .outer-container,
.container .inner-container {
  transform-style: preserve-3d;
}
/* 设置图片尺寸固定宽高200px */
.outer-container img {
  width: 200px;
  height: 200px;
}

/* 外层立方体样式 */
.outer-container .outer-top,
.outer-container .outer-bottom,
.outer-container .outer-right,
.outer-container .outer-left,
.outer-container .outer-front,
.outer-container .outer-back {
  position: absolute;
  top: 0;
  left: 0;
  width: 200px;
  height: 200px;
  border: 1px solid #fff;
  opacity: 0.3;
  transition: all 0.9s;
}

/* 全靠transform 属性撑起来了外面的六面体 */
.outer-top {
  transform: rotateX(90deg) translateZ(100px);
}

.outer-bottom {
  transform: rotateX(-90deg) translateZ(100px);
}

.outer-front {
  transform: rotateY(0deg) translateZ(100px);
}

.outer-back {
  transform: translateZ(-100px) rotateY(180deg);
}

.outer-left {
  transform: rotateY(90deg) translateZ(100px);
}

.outer-right {
  transform: rotateY(-90deg) translateZ(100px);
}

// 鼠标悬停 外面的六面体,六条边都往外扩出去,并且透明度变浅了,猫猫图片更清晰了
.cube:hover .outer-top {
  right: -70px;
  bottom: -70px;
  opacity: 0.8;
  transform: rotateX(90deg) translateZ(200px);
}

.container:hover .outer-bottom {
  right: -70px;
  bottom: -70px;
  opacity: 0.8;
  transform: rotateX(-90deg) translateZ(200px);
}

.container:hover .outer-front {
  right: -70px;
  bottom: -70px;
  opacity: 0.8;
  transform: rotateY(0deg) translateZ(200px);
}

.container:hover .outer-back {
  right: -70px;
  bottom: -70px;
  opacity: 0.8;
  transform: translateZ(-200px) rotateY(180deg);
}

.container:hover .outer-left {
  right: -70px;
  bottom: -70px;
  opacity: 0.8;
  transform: rotateY(90deg) translateZ(200px);
}

.container:hover .outer-right {
  right: -70px;
  bottom: -70px;
  opacity: 0.8;
  transform: rotateY(-90deg) translateZ(200px);
}

/* 设置里面的六面体样式 */
/* 嵌套的内层立方体样式 */
.inner-container > div {
  position: absolute;
  top: 35px;
  left: 35px;
  width: 130px;
  height: 130px;
}
/* 里面的六面体尺寸宽高设置130px */
.inner-container img {
  width: 130px;
  height: 130px;
}

.inner-top {
  transform: rotateX(90deg) translateZ(65px);
}

.inner-bottom {
  transform: rotateX(-90deg) translateZ(65px);
}

.inner-front {
  transform: rotateY(0deg) translateZ(65px);
}

.inner-back {
  transform: translateZ(-65px) rotateY(180deg);
}

.inner-left {
  transform: rotateY(90deg) translateZ(65px);
}

.inner-right {
  transform: rotateY(-90deg) translateZ(65px);
}
</style>

都看到这里了,求各位观众大佬们点个赞再走吧,你的赞对我非常重要