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

2018-11-05 23:23:02 +08:00
 southSu

前言

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

绘制过程:

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

∙ 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 个面 :

<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>


.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;
}

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

.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);
}

.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);
}

.cube-inner .single-side.s4{
    /*s4 背部,公众号:honeyBadger8*/
    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°,因为字是倒着的*/
}

.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)
}

.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);
}

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

∙ 添加高光 :

∙ CSS 360°旋转 :
.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); 
	}
}

∙ 跟随鼠标旋转 :

 ……
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;
}
 ……

结尾:

PS:如果您觉得文章不错,想获取更多前端内容,那就请关注下方的 公众号,有惊喜哦。

更多文章:

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

1434 次点击
所在节点    分享发现
3 条回复
southSu
2018-11-05 23:24:31 +08:00
考虑一千次,不如去做一次
犹豫一万次,不如实践一次
将来的你,一定会感谢现在奋斗的你。—晚上好,我是苏南,感谢耐心阅读完此文,晚安 !
ukhack
2018-11-07 17:43:49 +08:00
很棒!
southSu
2018-11-07 22:54:23 +08:00
@ukhack

很喜欢的一段话:
年轻时不拖累生你的人,
年老时不拖累你生的人。感谢大佬支持,更多文章可关注公众号哦,晚安

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/504819

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX