CSS 实现一个3d魔方

news2024/11/25 2:28:41

前言

👏CSS 实现一个3d魔方,速速来Get吧~
🥇文末分享源代码。记得点赞+关注+收藏!

1.实现效果

在这里插入图片描述

2.实现步骤

  • 魔方的一面为九个圆角正方形,定义正方形的宽高为–w,九个正方形的直接的间距为–gap,由此可以计算出父容器的宽/高,box-sizing为border-box

在这里插入图片描述

--w: 60px;
--gap: 10px;
--allW: calc(3 * var(--w) + 4 * var(--gap)); 
  • 魔方有六个面,定义六个面中格子的背景颜色,以及六个面的背景色
--c1: #f5e7a1;
--c2: skyblue;
--c3: #fff;
--c4: #97d497;
--c5: #801a1a;
--c6: orange;
--bg: #000;
  • 设置父容器宽高为–allW
<div class="container"></div>
.container {
  width: var(--allW);
  height: var(--allW);
}
  • 添加魔方元素的父元素,宽高与父容器一致,设置 transform-style: preserve-3d,指示元素的子元素应位于 3D 空间
<div class="container">
 + <div class="container-box"></div>
</div>
.container-box {
  border: 1px solid red;
  position: relative;
  width: var(--allW);
  height: var(--allW);
  transform-style: preserve-3d;
}
  • 在container-box添加魔方的其中一面cube-side,absolute定位,宽高与父元素一致,设置一定的圆角,内边距为gap
 <div class="container-box">
	+ <div class="cube-side"></div>
 </div>
.cube-side {
 width: 100%;
 height: 100%;
 position: absolute;
 background: var(--bg);
 border-radius: 7px;
 padding: var(--gap);
}
  • 在cube-side中添加一个宫格,设置color为c1,背景色为currentColor

currentColor:表示元素color属性的计算值。它能让原本不能默认通过属性或子元素继承的颜色属性继承。如果没有设置color就找父元素,一级一级找,直到根元素。

在这里插入图片描述

<div class="cube-side">
	+ <div class="cube-grid" style="--c: var(--c1)"></div>
</div>
.cube-side .cube-grid {
  width: var(--w);
  height: var(--w);
  border-radius: calc(var(--w) / 5);
  color: var(--c);
  background: currentColor;
}

为cube-side添加box-shadow,实现剩余的8个宫格(当然你也可以再写8个宫格,实现九宫格布局

box-shadow:
CSS box-shadow 属性用于在元素的框架上添加阴影效果。你可以在同一个元素上设置多个阴影效果,并用逗号将他们分隔开。该属性可设置的值包括阴影的 X 轴偏移量、Y 轴偏移量、模糊半径、扩散半径和颜色。

eg:
在这里插入图片描述

  • box-shadow添加第二个宫格

在这里插入图片描述

.cube-grid{
  box-shadow: calc(var(--w) + var(--gap)) 0 0 currentColor;
}
  • box-shadow添加第三个宫格

在这里插入图片描述

box-shadow: calc(var(--w) + var(--gap)) 0 0 currentColor, calc(var(--w) * 2 + var(--gap) * 2) 0 currentColor;
  • box-shadow添加第四个宫格

在这里插入图片描述

box-shadow: calc(var(--w) + var(--gap)) 0 0 currentColor,
 calc(var(--w) * 2 + var(--gap) * 2) 0 currentColor,
 0 calc(var(--w) + var(--gap)) currentColor;
  • 按照此规律,实现剩下的宫格

在这里插入图片描述

box-shadow: calc(var(--w) + var(--gap)) 0 0 currentColor,
  calc(var(--w) * 2 + var(--gap) * 2) 0 currentColor,
  0 calc(var(--w) + var(--gap)) currentColor,
  calc(var(--w) + var(--gap)) calc(var(--w) + var(--gap)) currentColor,
  calc(var(--w) * 2 + var(--gap) * 2) calc(var(--w) + var(--gap))
    currentColor,
  0 calc(var(--w) * 2 + var(--gap) * 2) currentColor,
  calc(var(--w) + var(--gap)) calc(var(--w) * 2 + var(--gap) * 2)
    currentColor,
  calc(var(--w) * 2 + var(--gap) * 2) calc(var(--w) * 2 + var(--gap) * 2)
    currentColor;
  • 这样,魔方的其中一面就完成了
  • container-box添加transform旋转

在这里插入图片描述

.container-box {
 + transform: rotate(45deg) rotateY(45deg) rotateZ(45deg);
}
  • 添加第二面cube-side,宫格实现方式一致,添加transform旋转,x方向旋转-180deg,z轴方向偏移为宽的2分之一

在这里插入图片描述

<div class="cube-side side-back">
 + <div class="cube-grid" style="--c: var(--c2)"></div>
</div>
.cube-side.side-back {
  transform: rotateX(-180deg) translateZ(calc(var(--allW) / 2));
 }
  • 添加第三面cube-side,宫格实现方式一致,添加transform旋转,y方向旋转90deg,z轴方向偏移为宽的2分之一

在这里插入图片描述

<div class="cube-side side-right">
 + <div class="cube-grid" style="--c: var(--c3)"></div>
</div>
.cube-side.side-right {
  transform: rotateY(90deg) translateZ(calc(var(--allW) / 2));
 }
  • 添加第四面cube-side,宫格实现方式一致,添加transform旋转,y方向旋转-90deg,z轴方向偏移为宽的2分之一

在这里插入图片描述

<div class="cube-side side-left">
 + <div class="cube-grid" style="--c: var(--c4)"></div>
</div>
.cube-side.side-left {
 transform: rotateY(-90deg) translateZ(calc(var(--allW) / 2));
}
  • 添加第五面cube-side,宫格实现方式一致,添加transform旋转,x方向旋转90deg,z轴方向偏移为宽的2分之一

在这里插入图片描述

<div class="cube-side side-top">
 + <div class="cube-grid" style="--c: var(--c5)"></div>
</div>
.cube-side.side-top {
 transform: rotateX(90deg) translateZ(calc(var(--allW) / 2));
}
  • 添加第六面cube-side,宫格实现方式一致,添加transform旋转,x方向旋转-90deg,z轴方向偏移为宽的2分之一

在这里插入图片描述

<div class="cube-side side-bottom">
 + <div class="cube-grid" style="--c: var(--c6)"></div>
</div>
.cube-side.side-bottom {
 transform: rotateX(-90deg) translateZ(calc(var(--allW) / 2));
}
  • 将第一面z轴方向偏移为宽的2分之一

在这里插入图片描述

<div class="cube-side side-front">
	<div class="cube-grid" style="--c: var(--c1)"></div>
</div>
.cube-side.side-front {
  transform: translateZ(calc(var(--allW) / 2));
}
  • 可以看到,从某些角度可以看见元素后面的颜色,为每面设置backface-visibility: hidden

backface-visibility:
CSS 属性 backface-visibility 指定当元素背面朝向观察者时是否可见。

在这里插入图片描述

.cube-side {
 + backface-visibility: hidden;
}
  • 去掉刚开始的border辅助线

在这里插入图片描述

.container-box {
 - border: 1px solid red;
}
  • 为container-box添加动画,进行transform旋转

在这里插入图片描述

.container-box {
 + animation: rotate 10s infinite alternate;
}
@keyframes rotate {
 0% {
   transform: rotateZ(0deg) rotateX(0deg) rotateY(0deg);
 }
 15% {
   transform: rotateZ(45deg) rotateX(45deg) rotateY(45deg);
 }
 30% {
   transform: rotateZ(45deg) rotateX(90deg) rotateY(90deg);
 }
 45% {
   transform: rotateZ(45deg) rotateX(135deg) rotateY(135deg);
 }
 60% {
   transform: rotateZ(45deg) rotateX(90deg) rotateY(180deg);
 }
 75% {
   transform: rotateZ(45deg) rotateX(45deg) rotateY(225deg);
 }
 100% {
   transform: rotateZ(45deg) rotateX(0deg) rotateY(270deg);
 }
}
  • 在最外层的父容器上添加perspective,改变透视效果,使之变得更加的协调

perspective:
CSS 属性 perspective 指定了观察者与 z=0 平面的距离,使具有三维位置变换的元素产生透视效果。z>0 的三维元素比正常大,而 z<0 时则比正常小,大小程度由该属性的值决定。

在这里插入图片描述

.container {
 + perspective: 900px;
}
  • 现在我们试着调整一下w和gap,就完成了啦~

在这里插入图片描述

--w: 30px;
--gap: 8px;
  • 当然,颜色也是可以调整的,这里就不在赘述了哈

3.实现代码

<!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>151.3d魔方</title>
  </head>
  <link rel="stylesheet" href="../common.css" />
  <style>
    :root {
      --bg: #000;
      --c1: #f5e7a1;
      --c2: skyblue;
      --c3: #fff;
      --c4: #97d497;
      --c5: #801a1a;
      --c6: orange;
      --w: 30px;
      --gap: 8px;
      --allW: calc(3 * var(--w) + 4 * var(--gap));
    }
    .container {
      width: var(--allW);
      height: var(--allW);
      perspective: 900px;
    }
    .container-box {
      position: relative;
      width: var(--allW);
      height: var(--allW);
      transform-style: preserve-3d;
      animation: rotate 5s infinite alternate;
    }
    .cube-side {
      width: 100%;
      height: 100%;
      position: absolute;
      background: var(--bg);
      border-radius: 7px;
      padding: var(--gap);
      backface-visibility: hidden;
    }
    .cube-side .cube-grid {
      width: var(--w);
      height: var(--w);
      border-radius: calc(var(--w) / 5);
      color: var(--c);
      background: currentColor;
      box-shadow: calc(var(--w) + var(--gap)) 0 0 currentColor,
        calc(var(--w) * 2 + var(--gap) * 2) 0 currentColor,
        0 calc(var(--w) + var(--gap)) currentColor,
        calc(var(--w) + var(--gap)) calc(var(--w) + var(--gap)) currentColor,
        calc(var(--w) * 2 + var(--gap) * 2) calc(var(--w) + var(--gap))
          currentColor,
        0 calc(var(--w) * 2 + var(--gap) * 2) currentColor,
        calc(var(--w) + var(--gap)) calc(var(--w) * 2 + var(--gap) * 2)
          currentColor,
        calc(var(--w) * 2 + var(--gap) * 2) calc(var(--w) * 2 + var(--gap) * 2)
          currentColor;
    }
    .cube-side.side-front {
      transform: translateZ(calc(var(--allW) / 2));
    }
    .cube-side.side-back {
      transform: rotateX(-180deg) translateZ(calc(var(--allW) / 2));
    }
    .cube-side.side-right {
      transform: rotateY(90deg) translateZ(calc(var(--allW) / 2));
    }
    .cube-side.side-left {
      transform: rotateY(-90deg) translateZ(calc(var(--allW) / 2));
    }
    .cube-side.side-top {
      transform: rotateX(90deg) translateZ(calc(var(--allW) / 2));
    }
    .cube-side.side-bottom {
      transform: rotateX(-90deg) translateZ(calc(var(--allW) / 2));
    }
    @keyframes rotate {
      0% {
        transform: rotateZ(0deg) rotateX(0deg) rotateY(0deg);
      }
      15% {
        transform: rotateZ(45deg) rotateX(45deg) rotateY(45deg);
      }
      30% {
        transform: rotateZ(45deg) rotateX(90deg) rotateY(90deg);
      }
      45% {
        transform: rotateZ(45deg) rotateX(135deg) rotateY(135deg);
      }
      60% {
        transform: rotateZ(45deg) rotateX(90deg) rotateY(180deg);
      }
      75% {
        transform: rotateZ(45deg) rotateX(45deg) rotateY(225deg);
      }
      100% {
        transform: rotateZ(45deg) rotateX(0deg) rotateY(270deg);
      }
    }
  </style>
  <body>
    <div class="container">
      <div class="container-box">
        <div class="cube-side side-front">
          <div class="cube-grid" style="--c: var(--c1)"></div>
        </div>
        <div class="cube-side side-back">
          <div class="cube-grid" style="--c: var(--c2)"></div>
        </div>
        <div class="cube-side side-right">
          <div class="cube-grid" style="--c: var(--c3)"></div>
        </div>
        <div class="cube-side side-left">
          <div class="cube-grid" style="--c: var(--c4)"></div>
        </div>
        <div class="cube-side side-top">
          <div class="cube-grid" style="--c: var(--c5)"></div>
        </div>
        <div class="cube-side side-bottom">
          <div class="cube-grid" style="--c: var(--c6)"></div>
        </div>
      </div>
    </div>
  </body>
</html>

4.写在最后🍒

看完本文如果觉得对你有一丢丢帮助,记得点赞+关注+收藏鸭 🍕
更多相关内容,关注🍥苏苏的bug,🍡苏苏的github,🍪苏苏的码云~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/79960.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring整合其他技术

Spring整合其他技术 1 Spring整合mybatis 1.1 思路分析 问题导入 mybatis进行数据层操作的核心对象是谁&#xff1f; 1.1.1 MyBatis程序核心对象分析 1.1.2 整合MyBatis 使用SqlSessionFactoryBean封装SqlSessionFactory需要的环境信息 使用MapperScannerConfigurer加载…

安卓玩机搞机技巧综合资源----手机显秒设置 多种方式【十一】

接上篇 安卓玩机搞机技巧综合资源------如何提取手机分区 小米机型代码分享等等 【一】 安卓玩机搞机技巧综合资源------开机英文提示解决dm-verity corruption your device is corrupt. 设备内部报错 AB分区等等【二】 安卓玩机搞机技巧综合资源------EROFS分区格式 小米红…

电子学会2020年9月青少年软件编程(图形化)等级考试试卷(二级)答案解析

目录 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 二、判断题&#xff08;共10题&#xff0c;每题2分&#xff0c;共20分&#xff09; 三、编程题【该题由测评师线下评分】&#xff08;共2题&#xff0c;共30分&#xff09; 青少年软件…

软件安全设计(威胁建模实现)

目录 一、实验目的 二、实验软硬件要求 三、实验预习 四、实验内容&#xff08;实验步骤、测试数据等&#xff09; 实验步骤 确定安全目标 创建在线学习系统概况图 分解在线学习系统 确定威胁 威胁评估 确定威胁缓解计划或策略 验证和记录威胁 一、实验目的 熟悉软…

[附源码]JAVA毕业设计医院管理系统(系统+LW)

[附源码]JAVA毕业设计医院管理系统&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&…

Spring Cloud Feign的自定义配置及使用

Feign 提供了很多的扩展机制&#xff0c;让用户可以更加灵活的使用&#xff0c;这节我们来学习 Feign 的一些自定义配置。 日志配置 有时候我们遇到 Bug&#xff0c;比如接口调用失败、参数没收到等问题&#xff0c;或者想看看调用性能&#xff0c;就需要配置 Feign 的日志了…

遥感影像(tif,img)概览/金字塔(overviews)的创建与清除

使用python环境下的gdal进行遥感影像&#xff08;tif&#xff0c;img格式&#xff09;概览&#xff08;overviews&#xff09;的创建与清除&#xff0c;前边是测试过程&#xff0c;结论在最后 过程 问题起因是拿到一批img格式的影像需要转cog&#xff0c;程序运行中报了个错 …

ESXi8.0安装,实体机安装,IPMI远程安装实战笔记

目录 1.前言 2.连接主板IMPI 3.硬件兼容及BIOS设置 4.从U盘安装ESXi ESXi8.0安装包下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1-a3ka1TAScFPtAc29jcxzQ 提取码&#xff1a;qwhg 1.前言 ESXi系列的虚拟机直接以操作系统的形态出现&#xff0c;与基于Li…

【Linux静态库和动态库】

Linux静态库和动态库1. 编译与ELF格式2. 库的基本概念3.静态库的制作&#xff1a;&#xff08;假设要将a.c、b.c制作成静态库&#xff09;4.静态库的常见操作5.静态库的使用6. 多个库的相互依赖举例1.(库文件制作、错误处理)7.静态库和动态库的关系和区别8.动态库的制作软链接 …

ADI Blackfin DSP处理器-BF533的开发详解25:USB接口设计(含源代码)

硬件准备 ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 硬件设计原理图 功能介绍 跟网口一样&#xff0c;USB这个设计很勉强&#xff0c;因为BF533并不带USB口&#xff0c;当时是给一个大厂做MP4的方案…

猿如意中的【UltraEdit】开发工具详情介绍

目录 一、工具名称 二、下载安装渠道 2.1 什么是猿如意&#xff1f; 2.2 如何下载猿如意&#xff1f; 2.3 如何在猿如意中下载UltraEdit&#xff1f; 三、UltraEdit介绍 四、软件安装过程 五、软件界面 六、UltraEdit功能特点介绍 七、UltraEdit使用/体验感受…

Python测试进阶(二)

文章目录简介selenium等待Web控件交互表单操作多窗口frame多浏览器处理用 js 操作文件上传弹窗pageObject复用浏览器简介 这部分主要介绍 web 自动化测试 selenium 专门测试 web 的工具&#xff0c;根据测试用例&#xff0c;直接在浏览器上执行对应动作还是在 pytest 框架中…

牛客网SQL入门复健小练

SQL3&#xff1a;distinct 查询结果去重&#xff0c;返回所有不同的university 方法一&#xff1a;distinct关键字。&#xff08;注意&#xff1a;这个关键字实际上是 select distinct&#xff0c;如果是多列&#xff0c;多列作为一个组合然后 distinct 去重&#xff09; 方…

[oeasy]python0028_直接运行_修改py文件执行权限_设置py文件打开方式

直接运行 回忆上次内容 我们把两个程序整合起来了 可以持续输出当前时间每秒都更新但是我想在 shell 里面 只输入文件名(./sleep.py)并回车就能不断输出时间可能吗&#xff1f;&#x1f914; import time while True:print(time.asctime())time.sleep(1) 尝试执行 第 1 句 根…

EXCEL基础:数据透视表(按月或月累计统计操作)

【按月统计数据】&#xff1a; 本操作实现的是原始数据是以日为单位&#xff0c;统计使用的时候&#xff0c;需要以月份或者季度、年份的形式进行&#xff0c;可以使用数据透视表的【组合】功能来 实现&#xff0c;如下所示&#xff1a; 如下所示&#xff0c;将日期字段放在行…

免费分享一套基于VuePress开发的markdown产品文档

vuepress-theme-jingli 文档 | 效果 | 本仓库的gitee镜像 &#xff08;进入赞助商扫码注册可为本项目作者充电~&#xff09; 介绍 这个主题的初衷是打造一个好用的、面向程序员的知识管理工具轻松构建一个结构化的知识库&#xff0c;让你的知识海洋像一本本书一样清晰易读。…

Mac 下设置VScode 背景图片失败解法

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言解法一&#xff1a;直接修改VScode 的CSS解法二&#xff1a;还是想用插件总结前言 仓库推荐 C/C 每日一练小仓库&#xff0c;慢慢学习C 知识必备仓库 https://…

Java8:SPI机制

参考资料&#xff1a; 《双亲委派机制及其弊端》 《Java中SPI机制深入及源码解析》 《Java SPI思想梳理》 《深入理解 Java 中 SPI 机制》 写在开头&#xff1a;本文为学习后的总结&#xff0c;可能有不到位的地方&#xff0c;错误的地方&#xff0c;欢迎各位指正。 目录 …

MyBatis-Plus联表查询的短板,终于有一款工具补齐了

mybatis-plus作为mybatis的增强工具&#xff0c;它的出现极大的简化了开发中的数据库操作&#xff0c;但是长久以来&#xff0c;它的联表查询能力一直被大家所诟病。一旦遇到left join或right join的左右连接&#xff0c;你还是得老老实实的打开xml文件&#xff0c;手写上一大段…

10.泛型算法

文章目录*泛型算法**10.1概述**10.2初识泛型算法**10.2.1只读算法**算法和元素类型**操作两个序列的算法**10.2.2写容器元素的算法**算法不检查写操作**介绍back_inserter**拷贝算法**10.2.3重排容器元素的算法**消除重复单词**使用unique**10.3定制操作**10.3.1向算法传递函数…