如何用CSS3画出懂你的3D魔方?

苏南South 2020-11-13 12:48:40
css CSS3 何用 画出 懂你


本文由@IT·平头哥联盟-首席填坑官(苏南)分享,公众号:honeyBadger8

作者:首席填坑官∙苏南
交流群:912594095、公众号:honeyBadger8,本文原创,著作权归作者所有,转载请注明原链接及出处。

前言

最近在写《每周动画点点系列》文章,上一期分享了< 手把手教你如何绘制一辆会跑车 >,本期给大家带来是结合CSS3画出来的一个立体3d魔方,结合了js让你随心所欲想怎么转,就怎么转,这里是 @IT·平头哥联盟,我是首席填坑官苏南(South·Su),我们先来看看效果,然后再分解它的实现过程吧

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8

绘制过程:

好吧,gif图看着好像有点不是很清晰,想在线预览的同学,可点击在线预览 ?,废话不多扯了,先来分析一下,看如何实现这个功能吧。

∙ API预热 :
  • 本次示例是一个立体的正方形,既然有立体效果,肯定少不了CSS3中的 -webkit-perspective-透视、preserve-3d-三维空间,这个两个是重点哦,当然还有transform-origintransitiontransform等,先来回故一下 API 怎么是讲的吧:

perspective 取值 :

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

transform-style 取值

  • flat :指定子元素位于此元素所在平面内;
  • preserve-3d :指定子元素定位在三维空间内,当该属性值为 preserve-3d时,元素将会创建局部堆叠上下文;

小结 :决定一个变换元素看起来是处在三维空间还是平面内,需要该元素的父元素上定义 <’ transform-style '> 属性,也就是说想某元素有三维效果,需要设定它的父级有 preserve-3d

transform-origin 取值

  • percentage:用百分比指定坐标值。可以为负值;
  • length:用长度值指定坐标值。可以为负值;
  • left:指定原点的横坐标为left;
  • center①:指定原点的横坐标为center;
  • right:指定原点的横坐标为right;
  • top:指定原点的纵坐标为top;
  • center②:指定原点的纵坐标为center;
  • bottom:指定原点的纵坐标为bottom;

transform、transition等,就不介绍了

/* perspective 使用示例:*/
div{

-webkit-perspective:600px;
perspective:600px;
}
/*transform-style 使用示例:*/
.preserve{

transform-style:preserve-3d;
-webkit-transform-style:preserve-3d;
}
/*transform-origin 使用示例:*/
.preserve{

-webkit-transform-origin:50% 50% -100px; or
-webkit-transform-origin:bottom; or
-webkit-transform-origin:top;
…………
}
∙ 绘制6个面 :
  • 是的,我没有说错,就是6个面:上、正面、下、背面、左、右,
  • 上面API讲了这么多,来实践试一下吧,写6个div,结构大概是这样的,也是接下来的魔方需要的结构:

<div class="cube">
<div class="cube-inner running">
<p class="single-side s1"><span></span></p>
<p class="single-side s2"><span></span></p>
<p class="single-side s3"><span></span></p>
<p class="single-side s4"><span></span></p>
<p class="single-side s5"><span></span></p>
<p class="single-side s6"><span></span></p>
</div>
</div>

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8

  • !!!发生了什么??是不是很吃惊??说好的值越大,透视效果越强的呢?后面明明藏了个妹子,怎么看没有透视出来?
  • 开始我也是跟你一样吃惊的,但瞬间就悟透了,少了rotate,加个它再来看看效果吧:

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8


.cube{

width:200px;
height:200px;
margin:10px auto;
padding:260px;
position:relative;
-webkit-perspective:600px;
perspective:600px;
transition: .5s ;
}
.cube-inner{

width:200px;
height:200px;
position:relative;
-webkit-transform-style:preserve-3d;
transition:.3s;
-webkit-transform-origin:50% 50% -100px;
transform: rotateX(45deg);
}
.cube:hover{

/*鼠标经过时,把 perspective 过渡到100 */
-webkit-perspective:100px;
perspective:100px;
}
  • 既然API有效,那么拉下来我们就画出6个面吧,按:上、正面、下、背面、左、右,这个顺序来设置吧;
  • 首先,我们要指定它们是在三维空间内的preserve-3d,也就是6个面的父级要设置 transform-style 样式;
  • 以上都设置好后,再来看看6个面吧,为了便于区分,给它们每个都设置了不同颜色(用了css3的渐变 radial-gradient)——不想手写的同学推荐一个网站可在线设置你要的效果,复制样式即可,先来一睹风采,为了便于观察,整体角度旋转了10deg:

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8

  • 说到渐变,偶然之间发现了一个有意思的东西hue-rotate,它能在你初始的颜色基础上旋转元素的色调及其内容,从而达到不同的效果。了解更多

hue-rotate : The hue-rotate() CSS function rotates the hue of an element and its contents. Its result is a .

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8

  • ** 上 ** - “”:
.cube-inner .single-side.s1{

/*s1顶部*/
left:0;top:-200px;
background: radial-gradient(circle, rgba(255,255,255,.88), #00adff);
background: -webkit-radial-gradient(circle, rgba(255,255,255,.88), #00adff);
transform-origin:bottom;
-webkit-transform-origin:bottom;
transform:rotateX(90deg);
-webkit-transform:rotateX(90deg);
}

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8

  • ** 正面 ** - “”:

    • 下面就是默认的,什么都不用设置,所以就不展示了 ;
  • ** 下面 ** - “”:

    • 即底部,底部的设置,正好跟顶部它是相反的,一个origin 以 bottom为基准为坐标,一个以top为基准为坐标;
.cube-inner .single-side.s3{

/*s3底部*/
left:0;top:200px;
background: radial-gradient(circle, rgba(255,255,255,.88), #100067);
background: -webkit-radial-gradient(circle, rgba(255,255,255,.88), #100067);
transform-origin:top;
-webkit-transform-origin:top;
transform:rotateX(-90deg);
-webkit-transform:rotateX(-90deg);
}

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8

  • ** 背面 ** - “”:
    • 即正面的后边,整体旋转了 135deg,让背面更直观能看到;
    • translateZ 、rotateX 同时移动,形成透视的关系,让它看起来,在正面面的后面;
    • 下图二,把默认的正面,设置了透明度,可以看出,背面的透视效果;
.cube-inner .single-side.s4{

/*s4背部*/
z-index:2;
left:0;top:0;
background: radial-gradient(circle, rgba(255,255,255,.88), #F0C);
background: -webkit-radial-gradient(circle, rgba(255,255,255,.88), #F0C);
transform:translateZ(-200px) rotateX(180deg) ;
-webkit-transform:translateZ(-200px) rotateX(180deg) ; /*rotateZ(-180deg) 左右旋转的时候,Z轴旋转180°,因为字是倒着的*/
}

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8

  • ** 左侧面 ** - “”:
    • origin以right为基准,left负元素的宽度,rotateY轴旋转90deg;
.cube-inner .single-side.s5{

/*s5左侧*/
left:-200px;top:0;
background: radial-gradient(circle, rgba(255,255,255,.88),rgba(33,33,33,1));
background: -webkit-radial-gradient(circle, rgba(255,255,255,.88),rgba(33,33,33,1));
transform-origin:right;
-webkit-transform-origin:right;
transform:rotateY(-90deg)
-webkit-transform:rotateY(-90deg)
}

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8

  • ** 右侧面 ** - “”:
    • 同理右侧,与左侧正好相反;
.cube-inner .single-side.s6{

/*s6右侧*/
right:-200px;top:0;
transform-origin:left;
-webkit-transform-origin:left;
background: radial-gradient(circle, rgba(255,255,255,.88), #f00);
background: -webkit-radial-gradient(circle, rgba(255,255,255,.88), #f00);
transform:rotateY(90deg);
-webkit-transform:rotateY(90deg);
}

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8

小结 : 嗯,以上魔方的6个面的绘制过程,基本已经完成,主要在在于transform-originrotatetranslate等属性的应用,但为了让它更炫酷一些,我们还要给边角加一些光感。

∙ 添加高光 :
  • 细心的宝宝,前面的布局应该已经发现了,每一行布局的p标签里,都多套了一层span,就是为高光光感,埋下的伏笔,一个平面正方形有四个边,after、before只有两,那么肯定要再套一层,当然方法很多,比如直接用border也是可以的,但比较麻烦,我就选择了现在要讲的这种:
  • after、before设置1px的边框,设置一个线性渐变,中间是白色,两断是过渡到透明的,这样高光就有了,来看一组图吧:

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8

∙ CSS 360°旋转 :
  • 上面是一个鼠标经过的过渡动画,可以看出立体效果是已经有了,接下来就写一个CSS animation的动画,让它360度旋转,每个角都能看到,这样会显的很666;
  • animation 配合 keyframes 使用,请看代码示例:
.cube .cube-inner{

/*-webkit-transform:rotateX(180deg) rotateY(0deg) ;*/
animation: elfCube 10s infinite ease-in-out;
-webkit-animation: elfCube 10s infinite ease alternate;
}
@keyframes elfCube {

0% {

transform: rotateX(0deg) rotateY(0deg);
}
50% {

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

transform: rotateX(0deg) rotateY(0deg);
}
}
@-webkit-keyframes elfCube {

0% {

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

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

transform: rotateX(0deg) rotateY(0deg);
}
}

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8

∙ 跟随鼠标旋转 :
  • 说好的随着鼠标旋转呢??
  • 别慌,接下来就是带你装逼,带你飞的时候,
    • 首先我们要了解,鼠标在容器内所在的位置,X = e.pageX - ele.offsetLeft, Y = e.pageY - ele.offsetTop;
    • 同时要知道元素内的中心点:centerX = width/2,centerY =height/2;
    • 然后得出值:axisX = X - centerX,axisY = Y - centerY;
    • PS : 开始尝试想的是鼠标从哪个方向进入,得到它的角度,但发现旋转效果不明显 ,有兴趣的同学可以尝试一下:(((Math.atan2(Y, X) * (180 / Math.PI)) + 180) / 90),参考司徒大神的JS判断鼠标从什么方向进入一个容器;
    • 最后,给容器绑上事件:mouseovermousemovemouseout,鼠标进入时,暂停css的动画,不然会相互打架哦!

本文由@IT·平头哥联盟-首席填坑官∙苏南分享,公众号:honeyBadger8

 ……
getAxisX(e){

let left = this.cubeEle.offsetLeft;
return e.pageX - left - (this.cubeW/2) * (this.cubeW>this.cubeH ? this.cubeH/this.cubeW : 1);
}
getAxisY(e){

let top = this.cubeEle.offsetTop;
return e.pageY - top - (this.cubeH/2) * (this.cubeH>this.cubeW ? this.cubeW/this.cubeH : 1);
}
…………
 …………
run(){

this.cubeEle.addEventListener('mouseover',(e)=>this.hoverOut(e),false);
this.cubeEle.addEventListener('mousemove',(e)=>this.move(e),false);
this.cubeEle.addEventListener('mouseout',(e)=>this.hoverOut(e),false);
}
hoverOut(e){

//进入/离开
e.preventDefault();
this.axisX = this.getAxisX(e),
this.axisY = this.getAxisY(e);
if(e.type == 'mouseout'){
 //离开
this.axisX=0;
this.axisY = 0;
console.log("离开")
this.cubeInner.className="cube-inner running";
}else{

this.cubeInner.className="cube-inner";
console.log("进入")
};
let rotate = `rotateX(${
-this.axisY}deg) rotateY(${
-this.axisX}deg)`;
this.cubeInner.style.WebkitTransform = this.cubeInner.style.transform = rotate;
}
……

结尾:

  • -webkit-perspective,
  • -webkit-transform-style,
  • -webkit-transform-origin,
  • radial-gradient、linear-gradient,
  • transform:rotate、translate、scale,
  • transition,
  • animation;
  • 以上就是今天为大家带来的分享,以及使用到的知识点的API,如文章中有不对之处,烦请各位大神斧正,
  • 文章源码获取-> blog-resource ?
  • 想直接在线预览 ?

宝剑锋从磨砺出,梅花香自苦寒来,做有温度的攻城狮!,公众号:honeyBadger8

更多文章:

做完小程序项目、老板给我加了6k薪资~
面试踩过的坑,都在这里了~
你应该做的前端性能优化之总结大全!
如何给localStorage设置一个过期时间?
手把手教你如何绘制一辆会跑车
SVG Sprites Icon的使用技巧
immutability因React官方出镜之使用总结分享!

作者:苏南 - 首席填坑官
链接:https://honeybadger8.github.io/blog/
交流:912594095、公众号:honeyBadger8
本文原创,著作权归作者所有。商业转载请联系@IT·平头哥联盟获得授权,非商业转载请注明原链接及出处。

宝剑锋从磨砺出,梅花香自苦寒来,做有温度的攻城狮

版权声明
本文为[苏南South]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_43254766/article/details/83472829

  1. [front end -- JavaScript] knowledge point (IV) -- memory leakage in the project (I)
  2. This mechanism in JS
  3. Vue 3.0 source code learning 1 --- rendering process of components
  4. Learning the realization of canvas and simple drawing
  5. gin里获取http请求过来的参数
  6. vue3的新特性
  7. Get the parameters from HTTP request in gin
  8. New features of vue3
  9. vue-cli 引入腾讯地图(最新 api,rocketmq原理面试
  10. Vue 学习笔记(3,免费Java高级工程师学习资源
  11. Vue 学习笔记(2,Java编程视频教程
  12. Vue cli introduces Tencent maps (the latest API, rocketmq)
  13. Vue learning notes (3, free Java senior engineer learning resources)
  14. Vue learning notes (2, Java programming video tutorial)
  15. 【Vue】—props属性
  16. 【Vue】—创建组件
  17. [Vue] - props attribute
  18. [Vue] - create component
  19. 浅谈vue响应式原理及发布订阅模式和观察者模式
  20. On Vue responsive principle, publish subscribe mode and observer mode
  21. 浅谈vue响应式原理及发布订阅模式和观察者模式
  22. On Vue responsive principle, publish subscribe mode and observer mode
  23. Xiaobai can understand it. It only takes 4 steps to solve the problem of Vue keep alive cache component
  24. Publish, subscribe and observer of design patterns
  25. Summary of common content added in ES6 + (II)
  26. No.8 Vue element admin learning (III) vuex learning and login method analysis
  27. Write a mini webpack project construction tool
  28. Shopping cart (front-end static page preparation)
  29. Introduction to the fluent platform
  30. Webpack5 cache
  31. The difference between drop-down box select option and datalist
  32. CSS review (III)
  33. Node.js学习笔记【七】
  34. Node.js learning notes [VII]
  35. Vue Router根据后台数据加载不同的组件(思考-&gt;实现-&gt;不止于实现)
  36. Vue router loads different components according to background data (thinking - & gt; Implementation - & gt; (more than implementation)
  37. 【JQuery框架,Java编程教程视频下载
  38. [jQuery framework, Java programming tutorial video download
  39. Vue Router根据后台数据加载不同的组件(思考-&gt;实现-&gt;不止于实现)
  40. Vue router loads different components according to background data (thinking - & gt; Implementation - & gt; (more than implementation)
  41. 【Vue,阿里P8大佬亲自教你
  42. 【Vue基础知识总结 5,字节跳动算法工程师面试经验
  43. [Vue, Ali P8 teaches you personally
  44. [Vue basic knowledge summary 5. Interview experience of byte beating Algorithm Engineer
  45. 【问题记录】- 谷歌浏览器 Html生成PDF
  46. [problem record] - PDF generated by Google browser HTML
  47. 【问题记录】- 谷歌浏览器 Html生成PDF
  48. [problem record] - PDF generated by Google browser HTML
  49. 【JavaScript】查漏补缺 —数组中reduce()方法
  50. [JavaScript] leak checking and defect filling - reduce() method in array
  51. 【重识 HTML (3),350道Java面试真题分享
  52. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  53. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  54. [re recognize HTML (3) and share 350 real Java interview questions
  55. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  56. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  57. 【重识 HTML ,nginx面试题阿里
  58. 【重识 HTML (4),ELK原来这么简单
  59. [re recognize HTML, nginx interview questions]
  60. [re recognize HTML (4). Elk is so simple