CSS 3D的魅力

Wesley13
• 阅读 632

CSS 3D的魅力

阅读文本大概需要 11.1分钟。

本文介绍了CSS来实现3D效果,并且有详细代码和解释。建议大家只字不差的阅读。本文的作者是「子慕大诗人」,点击「阅读原文」就可以跳转原地址。

前言:

最近玩了玩用css来构建3D效果,写了几个demo,所以博客总结一下。  在阅读这篇博客之前,请先自行了解一下css 3D的属性,例如:transform-style,transform-origin,transform, perspective。

demo1

高度可变的立方体,先来看看最终效果,自己弄得有点丑,如果设计师调下色,添加点元素应该会好看的多

  CSS 3D的魅力

1.  我们先用css实现一个长方体,一个长方体有6个边,我们写6个div,并用一个div包裹起来

<div class="cube-box">
    <div class="cube1 cube"></div>
    <div class="cube2 cube"></div>
    <div class="cube3 cube"></div>
    <div class="cube4 cube"></div>
    <div class="cube5 cube"></div>
    <div class="cube6 cube"></div></div>

2.  给.cube-box设置宽高以及preserve-3d属性保留子元素3d转换,子元素.cube全部绝对定位

.cube-box{
    transform-style: preserve-3d;
    width: 30px;
    height: 100px;
    position: relative;
}.cube{
    position: absolute;
    left: 0;
    top: 0;
}

3.  先写一个面.cube1,宽高100%等同于父元素的宽高,背景色为red,代码和效果如下

.cube1{
    width: 100%;
    height: 100%;
    background: red;
}

CSS 3D的魅力

4.  为了之后方便我们看到立体效果,现在我们旋转一下父元素,加入如下代码,效果如下

.cube-box{
    transform: rotateX(-30deg) rotateY(45deg);
}

CSS 3D的魅力

5.  .cube1作为第一个元素,我们不需要它旋转,它作为默认面,现在拼接第二个面.cube2,按照.cube1的写法,但是我们设置为绿色,效果如下,.cube2重叠在.cube1上,因此我们还需要旋转.cube2

.cube2{
    width: 100%;
    height: 100%;
    background: green;
}

CSS 3D的魅力

6.  我们现在试着旋转一下.cube2,变成了如下效果。关于rotate的旋转方向这里不解释,不懂的朋友可以自行查看其他文档。

.cube2{
    width: 100%;
    height: 100%;
    background: green;
    transform: rotateY(-90deg);
}

CSS 3D的魅力

7.  在用translate3d移动一下吧。  效果如下图,屌屌屌。  但是问题来了,这里的代码不够灵活,translate的值需要手动计算,现在宽是30px,需要移动它的一半15px进行拼接,这个值需要我们手动计算写上去,或者到时候用js计算,太low,我希望只需要用js根据后端数据动态设置父元素.cube-box的宽高,子元素全部自适应就行,这样才更好用。

.cube2{
    width: 100%;
    height: 100%;
    background: green;transform: rotateY(-90deg) translate3d(15px,0,15px);
}

CSS 3D的魅力

8.  因此现在我们要使用另一个属性transform-origin,transform-origin默认是“center center 0;”或者说“50% 50% 0;”,所以在第6个步骤的时候,我们旋转.cube2的时候是根据它自身中间的位置进行的旋转,我们改造一下,把转换的位置定在元素左边,也同样达到了效果,代码反而更简单了

.cube2{
    width: 100%;
    height: 100%;
    background: green;
    transform-origin: left top;
    transform: rotateY(-90deg);
}

CSS 3D的魅力  

9.  按照.cube2的方法我们给.cube3按照同样的写法旋转,并设置蓝色,效果如下

.cube3{
    width: 100%;
    height: 100%;
    background: blue;
    transform-origin: right top;
    transform: rotateY(90deg);
}

CSS 3D的魅力

10.  .cube4就有点不一样了,下一个面不需要旋转,只需要把.cube1向Z轴方向移动30px宽的位置,X和Y轴可以用width和height作为基数设置百分比,比如width是20px,如果要X轴移动20px,可以设置translateX(100%),但是Z就只能用具体值了。

所以这里我没有解决low的问题,我只能手动的写上translateZ的值,或者用js来动态赋值。  效果如下,如果有更好的方案,可以评论博客告知我。

.cube4{
    width: 100%;
    height: 100%;
    background: gray;
    transform-origin: right top;
    transform: translateZ(30px);
}

CSS 3D的魅力

11.  .cube5也就是顶面,我们的顶面和低面都是正方形的,.cube5如果写宽高100%就是长方形了,为了不手动或者动态写高度,这里使用了另一种写法设置width:100%;不设置height,设置padding-top:100%;

这样同样使.cube5变成了正方形,定义粉红色,延X轴旋转90度,代码和效果如下

.cube5{
    width: 100%;
    padding-top: 100%;
    background: pink;
    transform-origin: left top;
    transform: rotateX(90deg);
}

CSS 3D的魅力

12.   最后.cube6和.cube5写法一样,只是我们需要把位置绝对定位到底部,这时候把.cube类设置为透明度50%,方便我们查看,代码和效果如下

.cube6{
    width: 100%;
    padding-top: 100%;
    background: black;
    top: inherit;
    bottom: 0;
    transform-origin: left bottom;
    transform: rotateX(-90deg);
}

CSS 3D的魅力

13.  我们把每一个面都定义为红色,调整一下每一个面的颜色值,这样看起来就有视角的效果

CSS 3D的魅力

14.   现在长方体已经写好,我们来点动效吧,添加一个div.cube-wapper把刚才的cube-box再包裹一层,让cube-box绝对定位到父元素底部,这样高度变化的时候是向上延伸和收缩,js定时器每隔5秒改变一下box的高度,效果如下

let boxs = document.getElementsByClassName('cube-box');
setInterval(()=>{
    for(let item in boxs){
      if(boxs[item].style) boxs[item].style.height = `${Math.random()*300}px`;
    }
},5000)

CSS 3D的魅力

15.  不对啊,怎么底部还是有移动?  原因是我们tranform的rotate写在了.cube-box上,当高度改变的时候,会受到旋转的影响导致位置偏移,因此把.cube-box的tranform写到.cube-wrapper上去便没有这个问题了。效果如下

CSS 3D的魅力

demo2

一个圆柱体,因为被转换为gif效果有点差,实际运行会好很多。  这个的实现比较奇葩,在实际场合中几乎没有什么卵用,下面我还是大致说下实现方法吧。

CSS 3D的魅力

1.  还是和demo1差不多,先定义包裹层,定义preserve-3d,代码大致如下

<div class="wrapper">
    <div class="box" id="circles">
    </div>
</div><style>
.wrapper{
    transform-style: preserve-3d;
    width: 100px;
    height: 100px;
}.box{
    width: 100%;
    height: 100%;
    position: relative;
    transform-style: preserve-3d;
    transform: rotateX(-73.5deg) rotateY(5deg);
}</style>

2.  在box里插入n个div,每一个div样式相同设置为border-radius:50%和1px的border边框,唯一不同的是它们的translateZ位置相邻相差1,其实就是把1px的边框依次排列起来形成一个圆柱,这样会需要生成很多div,最后我们还是用js去生成我们需要的div数量。

let circles = document.getElementById('circles');for(let i=0;i<100;i++){
    let div = document.createElement('div');
    div.style = `transform: translateZ(${i}px)`;
    div.className = `circle ${i==0||i==99?'bg':''}`;
    circles.appendChild(div);
}

n个1px的div是无缝拼接起来的,为什么还是会有缝隙呢?  大家想象一张纸画了一个圈,从纸的最薄的一面看,是不是看不到圈了,如果再转换一点角度,也许也只能看到一点点,就是这个道理。如此方式我还试了下,写一个球,这里不传gif了,截图看看效果,github上会有代码可以亲自下载下来看看,效果还是挺神奇的

CSS 3D的魅力 CSS 3D的魅力           CSS 3D的魅力

 demo3

串挂的卡片效果,效果大致如下,像是挂在线上的6张照片,还带一点风吹的效果。  实际也非常简单,还是利用上面demo1的原理旋转卡片,再通过定位把卡片排列,定义一个无限循环的摇摆动画,给每个卡片使用不同的时间,最后绑定点击事件,给元素使用css过渡动画transition。

过渡动画保证元素改变或者还原的时候,都能有效果,所以过渡动画很适合用来做交互。  注意: 进行了3d转换后,要注意元素的可点击区域,用chrome调试工具查看比较准确。

CSS 3D的魅力

结语:

css 3d大部分时候使用场景不多,同时也比较消耗设备性能,如果有机会用到,能在网页中给用户体验带来那么一点点惊喜,也是不错的。

好了,我知道大家需要什么,仓库地址已经准备好 https://github.com/zimv/css3d。

推荐阅读:

推荐 | 不忘初心,方得始终

每天分享 前后端 干货

CSS 3D的魅力

本文分享自微信公众号 - Java后端(web_resource)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Sass
嵌套规则(NestedRules)Sass允许将一套CSS样式嵌套进另一套样式中,内层的样式将它外层的选择器作为父选择器mainp{color:00ff00;width:97%;.redbox{
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这