JavaScript实现的3D旋转魔方动画效果实例代码


Posted in Javascript onJuly 31, 2019

JS1K是JavaScript编程竞赛——参加竞赛的规则很简单,脚本必须小于1K,竞赛网站开始也只是为了娱乐,却意外地收到了很多优秀的作品。

这是2016年JS1k上传的作品,用几十行代码实现的一个3D旋转魔方:

JavaScript实现的3D旋转魔方动画效果实例代码

代码如下:

function z(t, e) {
  return t? e? t.appendChild(e) : "width:"+t+"px;height:"+t+"
px;position:absolute;" : document.createElement("div")
}

function w() {
  ++t==360&&(t=0, x=++x%3)
  for (i in m) 2 == m[i][s[x]] ? m[i][u][a] = r+s[x]+"(" + t + "deg)" : 0;
  c[u][a] = r+"3d(1,1,1," + t + "deg)", 
	requestAnimationFrame(w)
}
var a = "transform",
	p = "background-color:",
	y = a+"-style:preserve-3d;",
  u = "style",
  v = "cssText",
  B = z(),
  c = z(),
  t = x = 0,
  d, e, f, g, h, k, l, m = [], n, i, r="rotate", s = ["X","Y","Z"];

B[u][v] = "perspective:900px;"+z(600)+p+"#666";
c[u][v] = y + z(240) +"top:30%;left:30%", z(B, c), z(window.b, B);

for (l = 27; l--; z(c, f)) {
  f = z(), 
  f[u][v] = y + z(240), 
  f.X = g = l % 3, 
  f.Y = h = (l - g) % 9 / 3, 
  f.Z = k = ~~(l / 9), e = z(), 
  e[u][v] = y + z(80) +a+":translate3d(" + 80 * g + "px," + 
80 * h + "px," + 80 * (k-1) + "px)";
  for (n = 6; n--; z(e, d)) 
  	d = z(), 
  	d[u][v] = y + z(72) + "border-radius:9px;border:4px solid
 #000;opacity:0.9;"+a+":"+r+"X(" + (4 > n ? 90 * n : 0) 
 + "deg)"+r+"Y(" + (4 > n ? 0 : 4 == n ? -90 : 90) + "deg)translateZ(40px);"+p+ 
  	(0==n&&2==k?"#05C":1==n&&0==h?"#FD0":
 2==n&&0==k?"#0A6":3==n&&2==h?"#FFF":4==n&&0==g?"#F60":5==n&&2==g?"#C24":"#000");
  z(f, e), m.push(f)
}

w();

知识点扩展

JS如何实现旋转的魔方,浏览器从其他标签页回来依然匀速旋转?

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <div class="cube" onclick="stop()">
    <div class="front">front</div>
    <div class="back">back</div>
    <div class="left">left</div>
    <div class="right">right</div>
    <div class="top">top</div>
    <div class="bottom">bottom</div>
  </div>
</body>
<style>
  .cube {
    width: 400px;
    height: 400px;
    transition: all 3s;
    margin: 300px auto;
    /* 作用于所有3d转换的子元素 设置给父级 */
    /* perspective: 1000px; */
    /* transform: rotateX(30deg) rotateY(45deg); */
    /* 平面到立方 默认值:平面flat*/
    transform-style: preserve-3d;

    position: relative;
  }

  /* div:hover {
    transform: rotateY(90deg) translateZ(-200px);
    opacity: 0.5;
  } */
  .front,
  .back,
  .left,
  .right,
  .top,
  .bottom {
    width: 100%;
    height: 100%;
    text-align: center;
    line-height: 400px;
    position: absolute;
    opacity: 0.9;
    left: 0;
    top: 0;
  }

  .front {
    background-color: palevioletred;
    background-image: url('http://img1.gtimg.com/tj/pics/hv1/117/208/2153/140051982.jpg');
    transform: translateZ(200px);
  }

  .back {
    background-color: yellow;
    transform: translateZ(-200px);
    background-image: url('https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=841408372,3004217725&fm=11&gp=0.jpg');
  }

  .left {
    background-color: pink;
    background-image: url('https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2388632836,3966607624&fm=26&gp=0.jpg');
    transform: rotateY(90deg) translateZ(-200px)
  }

  .right {
    background-color: yellowgreen;
    background-image: url('https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=192610795,467565159&fm=26&gp=0.jpg');
    transform: rotateY(90deg) translateZ(200px)
  }

  .top {
    background-color: skyblue;
    background-image: url("https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2936477803,4198185787&fm=15&gp=0.jpg");
    transform: rotateX(90deg) translateZ(200px)
  }

  .bottom {
    background-color: orange;
    background-image: url('http://img0.pclady.com.cn/pclady/1611/02/1612285_jyz.jpg');
    transform: rotateX(90deg) translateZ(-200px)
  }
</style>
<script>
  window.onload = function () {
    let cube = document.querySelector('.cube')
    let timer = null
    let x = 0; y = 0;
    function rotate() {
      cube.style.transform = 'rotateX(' + x + 'deg)' + '' + 'rotateY(' + y + 'deg)';
      x += 30
      y += 45
    }
    function stop() {
      clearInterval(timer)
    }
    clearInterval(timer);
    timer = setInterval(() => {
      rotate();
    }, 1000);
    // 监听是否在当前页,并置为已读
    // document.addEventListener("visibilitychange", function () {
    //   if (document.hidden) {  //不处于当前页面
    //     // do something
    //     clearInterval(timer)
    //   } else {
    //     timer;
    //   }
    // });

    var hiddenProperty = 'hidden' in document ? 'hidden' :
      'webkitHidden' in document ? 'webkitHidden' :
        'mozHidden' in document ? 'mozHidden' :
          null;
    var visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange');
    var onVisibilityChange = function () {
      if (!document[hiddenProperty]) {
        timer = setInterval(() => {
          rotate();
        }, 1000);
        console.log(hiddenProperty);
      } else {
        clearInterval(timer)
      }
    }
    document.addEventListener(visibilityChangeEvent, onVisibilityChange);
    // document.addEventListener("visibilitychange", function () {
    //   if (!document.hidden) {  //处于当前页面
    //     timer = setInterval(() => {
    //       rotate();
    //     }, 1000);
    //     console.log('active');
    //   } else {
    //     clearInterval(timer);
    //     console.log('hidden');
    //   }
    // });
  }
</script>

</html>
Javascript 相关文章推荐
javascript中的关于类型转换的性能优化
Dec 14 Javascript
关于jQuery中的end()使用方法
Jul 10 Javascript
解决jquery异步按一定的时间间隔刷新问题
Dec 10 Javascript
window.showModalDialog参数传递中含有特殊字符的处理方法
Jun 06 Javascript
JavaScrip实现PHP print_r的数功能(三种方法)
Nov 12 Javascript
js取消单选按钮选中示例代码
Nov 14 Javascript
jquery左边浮动到一定位置时显示返回顶部按钮
Jun 05 Javascript
浅谈jquery点击label触发2次的问题
Jun 12 Javascript
Bootstrap简单表单显示学习笔记
Nov 15 Javascript
jQuery获取选中单选按钮radio的值
Dec 27 Javascript
jQuery插件DataTables分页开发心得体会
Aug 22 jQuery
layui监听单元格编辑前后交互的例子
Sep 16 Javascript
vue 实现滚动到底部翻页效果(pc端)
Jul 31 #Javascript
js实现一个简易计算器
Mar 30 #Javascript
微信小程序iBeacon测距及稳定程序的实现解析
Jul 31 #Javascript
JS获取动态添加元素的方法详解
Jul 31 #Javascript
JS/jQuery实现超简单的Table表格添加,删除行功能示例
Jul 31 #jQuery
详解Vuex下Store的模块化拆分实践
Jul 31 #Javascript
ES6 Iterator接口和for...of循环用法分析
Jul 31 #Javascript
You might like
php中判断一个字符串包含另一个字符串的方法
2007/03/19 PHP
PHP使用SOAP调用.net的WebService数据
2013/11/12 PHP
Mac系统下使用brew搭建PHP(LNMP/LAMP)开发环境
2015/03/03 PHP
php阳历转农历优化版
2016/08/08 PHP
laravel中的fillable和guarded属性详解
2019/10/23 PHP
jQuery 页面载入进度条实现代码
2009/02/08 Javascript
javascript函数重载解决方案分享
2014/02/19 Javascript
jQuery简易图片放大特效示例代码
2014/06/09 Javascript
分享一个自己动手写的jQuery分页插件
2014/08/28 Javascript
js中this用法实例详解
2015/05/05 Javascript
JS基于面向对象实现的拖拽库实例
2015/09/24 Javascript
浏览器环境下JavaScript脚本加载与执行探析之defer与async特性
2016/01/14 Javascript
JS使用onerror捕获异常示例
2016/08/03 Javascript
关于jquery form表单序列化的注意事项详解
2017/08/01 jQuery
详解Vue实战指南之依赖注入(provide/inject)
2018/11/13 Javascript
JS实现获取自定义属性data值的方法示例
2018/12/19 Javascript
vue.js实现的幻灯片功能示例
2019/01/18 Javascript
总结4个方面优化Vue项目
2019/02/11 Javascript
JS+DIV实现拖动效果
2020/02/11 Javascript
解决ant-design-vue中menu菜单无法默认展开的问题
2020/10/31 Javascript
Vue实现指令式动态追加小球动画组件的步骤
2020/12/18 Vue.js
用python分割TXT文件成4K的TXT文件
2009/05/23 Python
python将文本中的空格替换为换行的方法
2018/03/19 Python
Python3.5文件读与写操作经典实例详解
2019/05/01 Python
使用Pandas对数据进行筛选和排序的实现
2019/07/29 Python
基于python 微信小程序之获取已存在模板消息列表
2019/08/05 Python
Pytorch 实现自定义参数层的例子
2019/08/17 Python
python实现将一维列表转换为多维列表(numpy+reshape)
2019/11/29 Python
Python3 mmap内存映射文件示例解析
2020/03/23 Python
美国网上花店:JustFlowers
2017/02/12 全球购物
elf彩妆英国官网:e.l.f. Cosmetics英国(美国平价彩妆品牌)
2017/11/02 全球购物
台湾东南旅游社网站:东南旅游
2019/02/11 全球购物
Nip + Fab官网:英国美容品牌
2019/08/26 全球购物
路由表示做什么用的?在linux环境中怎么来配置一条默认路由?
2013/06/07 面试题
员工拾金不昧表扬信
2014/01/09 职场文书
试用期员工考核制度
2014/01/22 职场文书