<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
body {
background: gray;
}
#box {
width: 30px;
height: 490px;
background: black;
}
#box1 {
width: 30px;
height: 30px;
background: white;
}
#box2 {
/*设置魔方的位置*/
top: 0;
left: 0;
position: fixed;
transform-style: preserve-3d;
/*3d渲染*/
animation: cube_animation 3s linear infinite;
/*魔方动画设置 forwards属性表示当动画完成后保持最后一帧的属性*/
transform-origin: 15px 15px 0;
/*设置中心基点,以box所在的div的边框左上角为原点(0,0)*/
}
/*魔方动画效果*/
@keyframes cube_animation {
0% {
transform: rotateX(0) rotateY(0) rotateZ(45deg);
}
50% {
transform: rotateX(0) rotateY(360deg) rotateZ(45deg);
}
100% {
transform: rotateX(0) rotateY(720deg) rotateZ(45deg);
}
}
/*魔方六面*/
#whside {
width: 30px;
height: 30px;
position: absolute;
/*
* 白色面放在上面
* rotateX(90deg) 基点为由于每一个维度有四个面,每个面占据的角度为360deg/4=90deg
* translateZ(90px) 往外移动90px的距离
* */
transform: rotateX(90deg) translateZ(15px);
}
#whside div {
width: 8px;
height: 8px;
border-radius: 2px;
/*设置圆角才能看到格子与格子间的小孔*/
float: left;
/*没有top 和bottom*/
border: 1px solid #000;
/* 这里定义每个格子的边框是3px 所以一个格子总的长宽是8+1+1=30px 一行3个格子30*3=90px 一列同理 */
background: white;
/*上白色*/
}
#yeside {
width: 30px;
height: 30px;
position: absolute;
/*黄色面放在底面*/
transform: rotateX(-90deg) translateZ(15px);
}
#yeside div {
width: 8px;
height:8px;
border-radius: 2px;
float: left;
border: 1px solid #000;
background: yellow;
/*上黄色*/
}
#reside {
width: 30px;
height: 30px;
position: absolute;
/*红色面为正面,所以不用旋转,直接外移就可以了*/
transform: translateZ(15px);
}
#reside div {
width: 8px;
height:8px;
border-radius: 2px;
float: left;
border: 1px solid #000;
background: red;
/*上红色*/
}
#blside {
width: 30px;
height: 30px;
position: absolute;
/*蓝色面放在右面*/
transform: rotateY(90deg) translateZ(15px);
}
#blside div {
width: 8px;
height:8px;
border-radius: 2px;
float: left;
border: 1px solid #000;
background: blue;
/*上蓝色*/
}
#orside {
width: 30px;
height: 30px;
position: absolute;
/*橙色面放在后面*/
transform: rotateY(180deg) translateZ(15px);
}
#orside div {
width: 8px;
height:8px;
border-radius: 2px;
float: left;
border: 1px solid #000;
background: orange;
/*上橙色*/
}
#grside {
width: 30px;
height: 30px;
position: absolute;
/*绿色面放在左面 rotateY(-90deg)可以得到相同效果*/
transform: rotateY(-90deg) translateZ(15px);
}
#grside div {
width: 8px;
height:8px;
border-radius: 2px;
float: left;
border: 1px solid #000;
background: green;
/*上绿色*/
}
#btn {
width: 50px;
height: 30px;
right: 50px;
bottom: 50px;
position: fixed;
}
</style>
<body>
<div id="box">
<div id="box1">
<div id="box2">
<!--上面白色-->
<div id="whside">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<!--底部黄色-->
<div id="yeside">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<!--前面红色-->
<div id="reside">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<!--右面蓝色-->
<div id="blside">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<!--后面橙色-->
<div id="orside">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<!--左面绿色-->
<div id="grside">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
</div>
<button id="btn">点击</button>
</body>
<script type="text/javascript">
//获取按钮对象
var btn = document.getElementById("btn");
btn.onclick = function flow() {
var mofa = document.getElementById("box2"); //获取整个魔方对象
var winHeight = 490; //设置下落高度
var gSpeed = 9.8; //重力加速度
var firstV = 0; //初速度
var endV = Math.sqrt(2 * gSpeed * winHeight); //末速度
var limitHeight = winHeight; //判读位移是否越界
var top_px = 0; //魔方位置
var isFall = true; //判断是否处于下落状态
var t = 0; //已经经历过的时间
var shiftHeight = 0; //位移
//记录点击时的时间戳
var click_t = (new Date().getMinutes() * 60 * 1000) + (new Date().getSeconds() * 1000) + new Date().getMilliseconds();
//每隔time秒执行一次下面function()匿名函数
var timer = setInterval(function() {
//判断是否到达上下顶点(误差为0.01px)
if((limitHeight - shiftHeight) < 0.01) {
isFall = !isFall; //状态反转
endV = endV * 0.9; //设置弹起的速度为原来的下落的速度的90%;
if(isFall) {
firstV = 0; //下落时初速度重新设置为0
} else {
//限制高度重新计算:上抛的时候才重新计算限制高度,下落时不需要计算
limitHeight = (endV * endV) / (2 * gSpeed);
firstV = endV; //上抛时初速度重新设置为原来的末速度
}
shiftHeight = 0; //位移归零
//记录每次状态改变的时候的时间戳
click_t = (new Date().getMinutes() * 60 * 1000) + (new Date().getSeconds() * 1000) + new Date().getMilliseconds();
}
//获取时间差(本轮抛体运动开始到这一点的时间差)
t = (((new Date().getMinutes() * 60 * 1000) + (new Date().getSeconds() * 1000) + new Date().getMilliseconds()) - click_t);
//转化单位为秒
t = t / 1000;
t = t * 10; //加快物体降落的时间
if(isFall) {
//计算下拋位移
shiftHeight = (firstV * t) + (gSpeed * t * t / 2);
top_px = winHeight + shiftHeight - limitHeight; //魔方位置就是位移
} else {
//上抛位移
shiftHeight = (firstV * t) - (gSpeed * t * t / 2);
top_px = winHeight - shiftHeight;
}
//关闭定时器(误差为0.01px)
if(limitHeight <= 0.01) {
clearInterval(timer);
}
mofa.style.top = top_px + "px";
}, 0)
}
</script>
</html>