原生javascript+css3编写的3D魔方动画旋扭特效


Posted in Javascript onMarch 14, 2016

一直从事于后端编程工作,工作中也经常接触和使用一些前端技术,但大多数还是用于操作和控制数据与客户端交互工作。随着互联网技术的发展以及硬件性能的不断提升,人们对于交互式体验已变得越来越重视,进而前端技术已经越来越突显出它的重要性,特别是一些炫酷的特效,精美的UI设计,都使人眼前一亮,顿时觉得网站平台都高大上不少,很博人们眼球,给人们以很好的视觉冲击,特别是现在的css3,HTML5技术的更新,使得以更小的代价就可以轻松实现这些效果,故此,顿时膜拜起前端技术,悠然起了兴趣,跃跃欲试,随机利用css3的新增3D特效技术及动画特效功能加原生态javascript写了一个随机打乱旋扭的魔方,在指定的步数后,魔方按记录的动作,逆行旋扭重新归位。随即发布出来与大家分享,也希望前端的大牛能指点一二,不甚感激!

原生javascript+css3编写的3D魔方动画旋扭特效

代码如下:

<!DOCTYPE html>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 <title></title>
 <meta charset="utf-8" />
 <script language="javascript" type="text/javascript">
  var cache = {};
  (function (exports) {

   function Cube(opts) {
    opts = opts || {};
    this.parent = opts.parent; //插入到哪里
    this.browserPrefix = opts.browserPrefix;
    this.width = opts.width;
    this.height = opts.height;
    this.cubZ = opts.cubZ;
    this.face = opts.face;
    this.row = opts.row;
    this.column = opts.column;
    this.offsetX = this.column * (this.width + opts.marginX); //
    this.offsetY = this.row * (this.height + opts.marginY);//
    this.offsetZ = this.face * (this.cubZ + opts.marginZ);//
    this.positiveZ = this.cubZ / 2;
    this.negativeZ = -this.cubZ / 2;
    this.cubFaceInfo = opts.cubFaceInfo;
    this.dimension = opts.dimension;
    this.centerX = (this.dimension * this.width + (this.dimension - 1) * opts.marginX) / 2;
    this.centerY = (this.dimension * this.height + (this.dimension - 1) * opts.marginY) / 2;
    this.centerZ = (this.dimension * this.cubZ + (this.dimension - 1) * opts.marginZ) / 2;
    this.translateX = this.offsetX - this.centerX; //把中心点设为原点
    this.translateY = this.offsetY - this.centerY; //
    this.translateZ = this.cubZ / 2 + this.offsetZ - this.centerZ; //offsetZ按上面计算应该跟x,y在一个平面上即后面,但实际上由于要形成立方体,在Z轴上已经后退了cubZ/2个距离,故为和上面保持一致在一个面上,这里需要再加回cubZ/2个距离,使默认的xyz原点都在一个平面上即立方体后面左上角三维坐标系,以这个点作为参考点平移和设置旋转原点
    this.cubeFace = [];
    this.rotateTransfrom = "";
    this.init();

   }
   Cube.prototype = {
    init: function () {
     this.createCubeBox();
     this.createFront();
     this.createBack();
     this.createTop();
     this.createBottom();
     this.createLeft();
     this.createRight();

    },
    createCubeBox: function () {
     this.Box = document.createElement('div');
     this.Box.style.width = this.width + "px";
     this.Box.style.height = this.height + "px";
     this.Box.style.left = "50%";
     this.Box.style.top = "50%";
     this.Box.style.position = "absolute";
     this.Box.style[this.browserPrefix + "TransformStyle"] = "preserve-3d";
     this.Box.style[this.browserPrefix + "Perspective"] = "0";
     //     this.Scene.style[this.browserPrefix + "backfaceVisibility"] = "hidden";
     this.intalTransform = "translateZ(" + this.translateZ + "px) translateX(" + this.translateX + "px) translateY(" + this.translateY + "px)";
     this.Box.style[this.browserPrefix + "Transform"] = this.intalTransform;
     this.Box.style[this.browserPrefix + "TransformOrigin"] = "" + (-this.translateX) + "px " + (-this.translateY) + "px " + (-this.translateZ) + "px";
     this.parent.appendChild(this.Box);
     this.x = window.getComputedStyle(this.Box).getPropertyValue('left');
     this.y = window.getComputedStyle(this.Box).getPropertyValue('top');
     this.matrix3d = window.getComputedStyle(this.Box).getPropertyValue('transform');
    },
    createFace: function () {
     var face = document.createElement('div');
     face.style.margin = 0;
     face.style.position = "absolute";
     face.style.width = this.width + "px";
     face.style.height = this.height + "px";
     return face;
    },
    createFront: function () {
     var face = this.createFace();
     face.style[this.browserPrefix + "Transform"] = "translateZ(" + this.positiveZ + "px) "
     this.cubeFace.push(face);
     this.front = face;
     this.Box.appendChild(face);
    },
    createBack: function () {
     var face = this.createFace();
     face.style[this.browserPrefix + "Transform"] = "translateZ(" + this.negativeZ + "px) ";
     this.cubeFace.push(face);
     this.back = face;
     this.Box.appendChild(face);
    },
    createTop: function () {
     var face = this.createFace();
     face.style[this.browserPrefix + "Transform"] = "rotateX(90deg) translateZ(" + this.positiveZ + "px) ";
     this.cubeFace.push(face);
     this.top = face;
     this.Box.appendChild(face);
    },
    createBottom: function () {
     var face = this.createFace();
     face.style[this.browserPrefix + "Transform"] = "rotateX(90deg) translateZ(" + this.negativeZ + "px) ";
     this.cubeFace.push(face);
     this.bottom = face;
     this.Box.appendChild(face);
    },
    createLeft: function () {
     var face = this.createFace();
     face.style[this.browserPrefix + "Transform"] = "rotateY(90deg) translateZ(" + this.negativeZ + "px) ";
     this.cubeFace.push(face);
     this.left = face;
     this.Box.appendChild(face);
    },
    createRight: function () {
     var face = this.createFace();
     face.style[this.browserPrefix + "Transform"] = "rotateY(90deg) translateZ(" + (this.positiveZ) + "px) ";
     this.cubeFace.push(face);
     this.right = face;
     this.Box.appendChild(face);
    }

   }
   exports.magicCube = function (opts) {
    opts = opts || {};
    this.parent = opts.parent || document.getElementsByTagName('body')[0];
    this.dimension = opts.dimension || 3; //魔方级数
    this.cubWidth = opts.cubWidth || 50; //单个立方体宽度
    this.cubHidth = opts.cubHidth || 50; //单个立方体告诉
    this.marginLeft = opts.marginLeft || 0;
    this.marginTop = opts.marginLeft || 0;
    this.marginZ = opts.marginZ || 0;
    this.cubZ = opts.cubZ || 50; //单个立方体Z轴距离
    this.sceneWidth = opts.sceneWidth; //3d场景宽度
    this.sceneHeight = opts.sceneHeight; //3d场景高度
    this.Perspective = opts.Perspective || 0; //投影值
    this.cubFaceInfo = opts.cubFaceInfo || { front: { backGround: "rgba(0,255,255,.5)" }, back: { backGround: "rgba(153,204,255,.5)" }, left: { backGround: "rgba(128,0,128,.5)" }, right: { backGround: "rgba(255,0,255,.5)" }, top: { backGround: "rgba(255,153,204,.5)" }, bottom: { backGround: "rgba(0,204,255,.5)" }, inner: { backGround: "rgba(100,100,100,.5)" } }; //立方体面信息
    this.angle = opts.angle || 90;
    this.rollbackPoint = opts.rollbackPoint || 10;
    this.faceCount = this.dimension * this.dimension; //每面立方体个数
    this.count = this.dimension * this.dimension * this.dimension; //立方体总个数
    this.cubes = [];
    this.browserPrefix = "";
    this.isRunning = 0;
    this.timer = null;
    this.rotateFace;
    this.moveDirect = true;//正向随机动作还是回归,默认为正向
    this.cubeMoveQueue = [];
    this.rollMoveStack = [];//动作回归的堆栈
    this.init();
   };
   magicCube.prototype = {
    init: function () {
     this.start();
    },
    create3dScene: function () {
     this.Scene = document.createElement('div');
     //this.Scene.className = "cube";
     var width = this.sceneWidth || this.clientWidth,
      height = this.sceneHeight || this.clientHeight;
     this.Scene.style.width = width + "px";
     this.Scene.style.height = height + "px";
     this.Scene.style.position = "relative";
     this.Scene.style[this.browserPrefix + "TransformStyle"] = "preserve-3d";
     this.Scene.style[this.browserPrefix + "Perspective"] = this.Perspective + "px";
     //     this.Scene.style[this.browserPrefix + "backfaceVisibility"] = "hidden";
     this.Scene.style[this.browserPrefix + "Transform"] = "rotateX(-30deg) rotateY(30deg) ";
     this.parent.appendChild(this.Scene);

    },
    create: function (face, row, column) {
     return new Cube({
      parent: this.Scene,
      dimension: this.dimension,
      width: this.cubWidth,
      height: this.cubHidth,
      cubZ: this.cubZ,
      face: face,
      row: row,
      column: column,
      browserPrefix: this.browserPrefix,
      cubFaceInfo: this.cubFaceInfo,
      marginX: this.marginLeft,
      marginY: this.marginTop,
      marginZ: this.marginZ,
      dimension: this.dimension
     });
    },
    createMagicCube: function (index) {
     var face = 0, row = 0, column = 0;
     for (var i = 0; i < this.count; i++) {
      this.cubes.push(this.create(face, row, column));
      this.cubes[this.cubes.length - 1].index = this.cubes.length - 1;
      column++;
      if ((i + 1) % this.dimension === 0) {
       row++;
       column = 0;
      }
      if ((i + 1) % this.faceCount === 0) {
       face++;
       row = 0;
      }
     }
    },
    drawBackGroundColor: function () {
     for (var face in this.cubFaceInfo) {
      if (face == "inner") {
       this.setInnerBKColor(this.cubFaceInfo[face].backGround);
      }
      else {
       var cube = this.getCubesByFace(face);
       for (var i = 0, len = cube.length; i < len; i++) {
        cube[i][face].style.background = this.cubFaceInfo[face].backGround;
       }
      }
     }

    },
    setInnerBKColor: function (color) {
     for (var i = 0; i < this.count; i++) {
      for (var j = 0; j < 6; j++) {
       if (this.cubes[i].cubeFace[j].style.background == "") {
        this.cubes[i].cubeFace[j].style.background = color;
       }
      }
     }
    },
    getZFace: function (zIndex) {
     var zFace = [];
     if (zIndex < 1 || zIndex > this.dimension)
      return null;
     for (var i = (zIndex - 1) * this.faceCount; i < zIndex * this.faceCount; i++) {
      zFace.push(this.cubes[i]);
     }
     return zFace;
    },
    getXFace: function (xIndex) {
     var xFace = [];
     if (xIndex < 1 || xIndex > this.dimension)
      return null;
     for (var i = 0; i < this.count; i++) {
      if (i % this.dimension == 0)
       xFace.push(this.cubes[i + xIndex - 1]);
     }
     return xFace;
    },
    getYFace: function (yIndex) {
     var yFace = [];
     if (yIndex < 1 || yIndex > this.dimension)
      return null;
     for (var i = 0; i < this.count; i++) {
      if (i % this.faceCount == (yIndex - 1) * this.dimension) {
       for (var j = 0; j < this.dimension; j++)
        yFace.push(this.cubes[i + j]);
      }
     }
     return yFace;
    },
    getSideCubes: function (cubes, circleIndex) {
     var sides = [], top = [], left = [], bottom = [], right = [];
     if (circleIndex < 0 || circleIndex > this.dimension / 2 - 1)
      return null;
     for (var i = 0, count = this.dimension - circleIndex * 2; i < count; i++) {
      top.push(cubes[circleIndex * this.dimension + circleIndex + i]);
      left.push(cubes[circleIndex * this.dimension + circleIndex + i * this.dimension]);
      bottom.push(cubes[(this.dimension - 1 - circleIndex) * this.dimension + circleIndex + i]);
      right.push(cubes[circleIndex * this.dimension + circleIndex + i * this.dimension + (this.dimension - (circleIndex * 2) - 1)]);
     }
     sides.push(this.orderByDesc(top));
     sides.push(left);
     sides.push(bottom);
     sides.push(this.orderByDesc(right));
     return sides;
    },

    getCubesByFace: function (face) {
     switch (face) {
      case "front": return this.getZFace(this.dimension);
      case "back": return this.getZFace(1);
      case "left": return this.getXFace(1);
      case "right": return this.getXFace(this.dimension);
      case "top": return this.getYFace(1);
      case "bottom": return this.getYFace(this.dimension);
     }
    },
    moveMagicCube: function () {
     if (this.cubes.length < 1) return;
     //var cubes = this.getYFace(2);
     //for (var i = 0, len = cubes.length; i < len; i++) {
     // cubes[i].Box.className = "rotate";
     //}
     //随机产生3D转动方向
     this.isRunning = 0;
     var direct = this.random(1, 3), rotateDirect = "", getFaceFun;
     // direct=3;
     switch (direct) {
      case 1: rotateDirect = "rotateX"; getFaceFun = this.getXFace; break;
      case 2: rotateDirect = "rotateY"; getFaceFun = this.getYFace; break;
      case 3: rotateDirect = "rotateZ"; getFaceFun = this.getZFace; break;
     }
     this.rotateFace = rotateDirect;
     this.cubeRotateStatus = [];
     for (var i = 1; i <= this.dimension; i++) {
      var status = this.random(0, 2);
      this.cubeRotateStatus.push(status);
      switch (status) {
       case 0: break;//不转动
       case 1: this.rotateBox(this.angle, rotateDirect, i, getFaceFun.call(this, i)); break;//正向转动90
       case 2: this.rotateBox(-this.angle, rotateDirect, i, getFaceFun.call(this, i)); break;//反向转动90
      }

     }

     var flag = false;
     for (var i = 0, len = this.cubeRotateStatus.length; i < len; i++) {
      if (this.cubeRotateStatus[i]) {
       flag = true;
       break;
      }
     }
     if (!flag) {//一个都没转的情况 则强制补充一个
      var index = this.random(1, this.dimension);
      this.rotateBox(this.angle, rotateDirect, index, getFaceFun.call(this, index)); //正向转动90
      this.cubeRotateStatus[index - 1] = 1;//全都不转动 默认选出一个 使其正向转动指定度数
     }
     setTimeout(this.timerFun, 100);
     this.rollMoveStack.push({ rotateFace: this.rotateFace, cubeRotateStatus: this.cubeRotateStatus });//记录动作状态
     if (this.rollMoveStack.length == this.rollbackPoint)//判断当达到阀值时切换动作方向为回归
      this.moveDirect = false;

    },
    moveRollBackCube: function () {
     var record = this.rollMoveStack.pop(), getFaceFun;
     this.rotateFace = record.rotateFace;
     this.isRunning = 0;
     switch (record.rotateFace) {
      case "rotateX": getFaceFun = this.getXFace; break;
      case "rotateY": getFaceFun = this.getYFace; break;
      case "rotateZ": getFaceFun = this.getZFace; break;
     }
     this.cubeRotateStatus = [];
     for (var i = 0, len = record.cubeRotateStatus.length; i < len; i++) {
      var dimensionIndex = i+1, status = record.cubeRotateStatus[i];
      if (status == 1) {
       this.cubeRotateStatus.push(2);//1 变2,2变1
       this.rotateBox(-this.angle, record.rotateFace, dimensionIndex, getFaceFun.call(this, dimensionIndex)); //反向转动90
      }
      else if (status == 2) {
       this.cubeRotateStatus.push(1);//1 变2,2变1
       this.rotateBox(this.angle, record.rotateFace, dimensionIndex, getFaceFun.call(this, dimensionIndex)); //反向转动90
      }
      else {
       this.cubeRotateStatus.push(0);
      }
     }
     setTimeout(this.timerFun, 100);
     if (this.rollMoveStack.length == 0)//判断当达到0时切换动作为正向随机
      this.moveDirect = true;
    },
    intersect: function (source, target) {
     var data = [];
     for (var i = 0, len = source.length; i < len; i++) {
      var index = target.indexOf(source[i]);
      if (index >= 0)
       data.push(source[i])
     }
     return data;
    },
    orderByDesc: function (datas) {
     var temp;
     for (var i = 0; i < datas.length - 1; i++) {
      for (var j = i + 1; j < datas.length; j++) {
       if (parseFloat(datas[i].index) < parseFloat(datas[j].index)) {
        temp = datas[i];
        datas[i] = datas[j];
        datas[j] = temp;
       }
      }
     }
     return datas;
    },
    getSideBackGround: function (sideFaces, face) {
     var backGrounds = [];
     for (var i = 0, len = sideFaces.length; i < len; i++) {
      backGrounds.push(sideFaces[i][face].style.background);
     }
     return backGrounds;
    },
    setRotateDirectSideBackGround: function (faceCubes, sideFace, offset, status) {
     var oldSides = this.getSideCubes(faceCubes, 0), backColor = [];
     var offsetNIndex, offsetPIndex;
     for (var j = 0; j < 4; j++) {
      offsetPIndex = (j - offset + 4) % 4;
      offsetNIndex = (j + offset) % 4;
      if (this.rotateFace == "rotateY") {
       if (status == 1)//正向
       {
        backColor[j] = this.getSideBackGround(oldSides[offsetPIndex], sideFace[offsetPIndex]);
       }
       else//反向
       {
        backColor[j] = this.getSideBackGround(oldSides[offsetNIndex], sideFace[offsetNIndex]);
       }
      }
      else {
       if (status == 2)//正向
       {
        backColor[j] = this.getSideBackGround(oldSides[offsetPIndex], sideFace[offsetPIndex]);
       }
       else//反向
       {
        backColor[j] = this.getSideBackGround(oldSides[offsetNIndex], sideFace[offsetNIndex]);
       }
      }

     }
     for (var j = 0; j < 4; j++) {
      for (var k = 0; k < oldSides[j].length; k++) {
       oldSides[j][k][sideFace[j]].style.background = backColor[j][k];
      }
     }
    },
    setRotateOtherDirectSideBackGround: function (faceCubes, otherFace, offset, status) {
     var oldSides = [], backColor = [];
     var offsetNIndex, offsetPIndex;
     for (var i = 0; i <= parseInt(this.dimension / 2) - 1; i++) {
      oldSides = this.getSideCubes(faceCubes, i), backColor = [];
      for (var j = 0; j < 4; j++) {
       offsetPIndex = (j - offset + 4) % 4;
       offsetNIndex = (j + offset) % 4;
       if (this.rotateFace == "rotateY") {
        if (status == 1)//正向
        {
         backColor[j] = this.getSideBackGround(oldSides[offsetPIndex], otherFace);
        }
        else//反向
        {
         backColor[j] = this.getSideBackGround(oldSides[offsetNIndex], otherFace);
        }
       }
       else {
        if (status == 2)//正向
        {
         backColor[j] = this.getSideBackGround(oldSides[offsetPIndex], otherFace);
        }
        else//反向
        {
         backColor[j] = this.getSideBackGround(oldSides[offsetNIndex], otherFace);
        }
       }

      }
      for (var j = 0; j < 4; j++) {
       for (var k = 0; k < oldSides[j].length; k++) {
        oldSides[j][k][otherFace].style.background = backColor[j][k];
       }
      }
     }

    },
    animationEnd: function () {
     var offset = this.angle / 90, faceCubes = [], otherFace;
     var zSideFace = ["top", "left", "bottom", "right"], xSideFace = ["back", "top", "front", "bottom"], ySideFace = ["back", "left", "front", "right"], sideFace = [];
     for (var i = 0, len = this.cubeRotateStatus.length; i < len; i++) {
      var status = this.cubeRotateStatus[i];
      if (status) {
       var dimensionIndex = i + 1;
       switch (this.rotateFace) {
        case "rotateX": faceCubes = this.getXFace(dimensionIndex); sideFace = xSideFace; if (dimensionIndex == 1) otherFace = "left"; else if (dimensionIndex == this.dimension) otherFace = "right"; break;
        case "rotateY": faceCubes = this.getYFace(dimensionIndex); sideFace = ySideFace; if (dimensionIndex == 1) otherFace = "top"; else if (dimensionIndex == this.dimension) otherFace = "bottom"; break;
        case "rotateZ": faceCubes = this.getZFace(dimensionIndex); sideFace = zSideFace; if (dimensionIndex == 1) otherFace = "back"; else if (dimensionIndex == this.dimension) otherFace = "front"; break;
       }
       this.setRotateDirectSideBackGround(faceCubes, sideFace, offset, status);
       if (dimensionIndex == 1 || dimensionIndex == this.dimension)
        this.setRotateOtherDirectSideBackGround(faceCubes, otherFace, offset, status);
      }

     }
     // console.info(this.rollMoveStack.length + "," + this.moveDirect);
     if (this.moveDirect)
      this.moveMagicCube();
     else
      this.moveRollBackCube();
     // alert("运行结束");
    },
    bindAnimationEvent: function () {
     var loopMove = function () {
      cache.magicCube.isRunning--;//由于按组转动,顾要等组成员都完成再进行新的动画
      if (cache.magicCube.isRunning == 0)
       cache.magicCube.animationEnd();
     }
     for (var i = 0; i < this.count; i++) {

      this.prefixedEvent(this.cubes[i].Box, "AnimationEnd", loopMove, true);
     }
     cache.magicCube = this;//缓存,避免内存泄露
    },
    rotateBox: function (angle, rotateDirect, faceIndex, cubes) {
     if (cubes != null) {
      var startStatus = rotateDirect + "(0deg)", endStatus = rotateDirect + "(" + angle + "deg)";
      // this.changeAnimationStatus("mydhua", startStatus, endStatus)
      for (var i = 0, len = cubes.length; i < len; i++) {
       var ruleName = "roateRule" + faceIndex + i;
       this.isRunning++;//组成员转动统计
       //if (cubes[i].rotateTransfrom != "")
       // startStatus = cubes[i].rotateTransfrom;
       cubes[i].rotateTransfrom = endStatus;
       if (this.findKeyframesRule(ruleName) == null)
        this.createKeyframesRule(ruleName, cubes[i].intalTransform + " " + startStatus, cubes[i].intalTransform + " " + endStatus);
       else
        this.changeAnimationStatus(ruleName, cubes[i].intalTransform + " " + startStatus, cubes[i].intalTransform + " " + endStatus);
       cubes[i].Box.style[this.browserPrefix + "AnimationName"] = "none";
       this.cubeMoveQueue.push({ cube: cubes[i], rule: ruleName });
      }
     }
    },
    findKeyframesRule: function (rule) {
     var ruleName = this.browserPrefix == "" ? "KEYFRAMES_RULE" : this.browserPrefix.toUpperCase() + "_KEYFRAMES_RULE";
     var ss = document.styleSheets;
     for (var i = 0; i < ss.length; ++i) {
      for (var j = 0; j < ss[i].cssRules.length; ++j) {
       if (ss[i].cssRules[j].type == window.CSSRule[ruleName] && ss[i].cssRules[j].name == rule) { return ss[i].cssRules[j]; }
      }
     }
     return null;
    },
    createKeyframesRule: function (rule, startStatus, endStatus) {
     var prefix = this.browserPrefix == "" ? "" : "-" + this.browserPrefix + "-";
     var sheet;
     if (document.styleSheets.length < 1)
      sheet = this.createSheets();
     else
      sheet = document.styleSheets[0];
     var selectorText = "@" + prefix + "keyframes " + rule;
     var cssText = "0% { " + prefix + "transform: " + startStatus + "; } 100% { " + prefix + "transform: " + endStatus + "; }"
     if (sheet.insertRule) {
      sheet.insertRule(selectorText + "{" + cssText + "}", 0);
     } else if (sheet.addRule) {//兼容IE
      sheet.addRule(selectorText, cssText, 0);
     }
    },
    removeKeyframeRule: function (keyframes) {
     var length = keyframes.cssRules.length;
     var keyframeString = [];
     for (var i = 0; i < length; i++) {
      keyframeString.push(keyframes.cssRules[i].keyText);
     }
     //移除动画帧规则
     for (var i = 0, j = length; i < j; i++) {
      if (this.browserPrefix == "webkit" || this.browserPrefix == "Moz")
       keyframes.deleteRule(keyframeString[i]);
      else
       keyframes.deleteRule(i); //兼容IE
     }
    },
    changeAnimationStatus: function (animationName, startStatus, endStatus) {
     var keyframes = this.findKeyframesRule(animationName);
     this.removeKeyframeRule(keyframes);
     //重新设置帧规则
     var prefix = this.browserPrefix == "" ? "" : "-" + this.browserPrefix + "-";
     keyframes.appendRule("0% { " + prefix + "transform: " + startStatus + "; }");
     keyframes.appendRule("100% { " + prefix + "transform: " + endStatus + "; }");
    },
    createSheets: function () {
     // 创建 <style> 标签
     var style = document.createElement("style");
     // 可以添加一个媒体(/媒体查询,media query)属性
     // style.setAttribute("media", "screen")
     // style.setAttribute("media", "only screen and (max-width : 1024px)")
     // 对WebKit hack :(
     style.appendChild(document.createTextNode(""));
     // 将 <style> 元素加到页面中
     document.head.appendChild(style);
     return style.sheet;
    },
    prefixedEvent: function (element, type, callback, isAdd) {
     var pfx = ["webkit", "moz", "MS", "o", ""];
     for (var p = 0; p < pfx.length; p++) {
      if (!pfx[p]) type = type.toLowerCase();
      if (isAdd)
       element.addEventListener(pfx[p] + type, callback, false);
      else
       element.removeEventListener(pfx[p] + type, callback, false);
     }
    },
    start: function () {
     this.css();
     this.prefix();
     this.create3dScene();
     this.createMagicCube();
     this.drawBackGroundColor();
     this.bindAnimationEvent();//绑定动画播放完成事件
     this.moveMagicCube();  //立即开始动画
     // this.timer = setInterval(this.timerFun, 100);
    },
    timerFun: function () {
     var _this = cache.magicCube;
     if (_this.isRunning >= _this.dimension) {
      for (var i = 0, len = _this.cubeMoveQueue.length; i < len; i++) {
       var animation = _this.cubeMoveQueue.shift();
       animation.cube.Box.style[_this.browserPrefix + "Animation"] = animation.rule + " 2s linear 1"; // Chrome, Safari 和 Opera 代码
      }

     }

    },
    css: function () {
     var d = document,
      doc = d.documentElement,
      body = d.body;
     this.clientWidth = doc.clientWidth;
     this.clientHeight = doc.clientHeight;
     if (d.compatMode != "CSS1Compat") {
      this.clientWidth = body.clientWidth;
      this.clientHeight = body.clientHeight;
     }
     // console.log(this.width +'////'+ this.height)
    },
    random: function (min, max) {
     return (Math.random() * (max - min + 1) + min) >> 0;
    },
    prefix: function () {
     var N = navigator.appName, ua = navigator.userAgent, tem;
     var M = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
     if (M && (tem = ua.match(/version\/([\.\d]+)/i)) != null) M[2] = tem[1];
     M = M ? [M[1], M[2]] : [N, navigator.appVersion, '-?'];
     M = M[0];
     if (M == "Chrome") { this.browserPrefix = "webkit"; }
     if (M == "Firefox") { this.browserPrefix = "Moz"; }
     if (M == "Safari") { this.browserPrefix = "webkit"; }
     if (M == "MSIE") { this.browserPrefix = "ms"; }
    }

   };
  }(window));


 </script>

</head>
<body style="background-color:black">
 <script>
  var cube = new magicCube({ parent: null, dimension: 3, cubWidth: 100, cubHidth: 100, marginLeft: 10, marginTop: 10, marginZ: 10, cubZ: 100 });
 </script>

</body>
</html>

 注:在此基础上可以加上鼠标控制事件,可以直接通过鼠标控制器任意方向的旋扭,也可以稍加改进用于炫酷展示图片!后续有时间我将加上这些功能,与大家再次分享!

Javascript 相关文章推荐
WEB 浏览器兼容 推荐收藏
May 14 Javascript
js关闭模态窗口刷新父页面或跳转页面
Dec 13 Javascript
JS 两日期相减,获得天数的小例子(兼容IE,FF)
Jul 01 Javascript
JS获取地址栏参数的几种方法小结
Feb 28 Javascript
jquery插件开发之实现jquery手风琴功能分享
Mar 10 Javascript
gulp-uglify 与gulp.watch()配合使用时报错(重复压缩问题)
Aug 24 Javascript
js 索引下标之li集合绑定点击事件
Jan 12 Javascript
vue 微信授权登录解决方案
Apr 10 Javascript
Vue结合Video.js播放m3u8视频流的方法示例
May 04 Javascript
vue 本地服务不能被外部IP访问的完美解决方法
Oct 29 Javascript
JS中间件设计模式的深入探讨与实例分析
Apr 11 Javascript
在elementui中Notification组件添加点击事件实例
Nov 11 Javascript
基于javascript html5实现3D翻书特效
Mar 14 #Javascript
php基于redis处理session的方法
Mar 14 #Javascript
使用javascript插入样式
Mar 14 #Javascript
jQuery实现百叶窗焦点图动画效果代码分享(附源码下载)
Mar 14 #Javascript
javascript实现数组去重的多种方法
Mar 14 #Javascript
javascript实现PC网页里的拖拽效果
Mar 14 #Javascript
Jquery实现简单的轮播效果(代码管用)
Mar 14 #Javascript
You might like
php at(@)符号的用法简介
2009/07/11 PHP
php中判断文件存在是用file_exists还是is_file的整理
2012/09/12 PHP
Yii基于数组和对象的Model查询技巧实例详解
2015/12/28 PHP
tp5(thinkPHP5)框架数据库Db增删改查常见操作总结
2019/01/10 PHP
Laravel获取所有的数据库表及结构的方法
2019/10/10 PHP
用jQuery打造TabPanel效果代码
2010/05/22 Javascript
jQuery 源码分析笔记(2) 变量列表
2011/05/28 Javascript
JavaScript实现算术平方根算法-代码超简单
2015/09/11 Javascript
解决jquery中动态新增的元素节点无法触发事件问题的两种方法
2015/10/30 Javascript
JavaScript黑洞数字之运算路线查找算法(递归算法)实例
2016/01/28 Javascript
基于jquery实现最简单的选项卡切换效果
2016/05/08 Javascript
自制微信公众号一键排版工具
2016/09/22 Javascript
JS+Canvas实现的俄罗斯方块游戏完整实例
2016/12/12 Javascript
JS 实现计算器详解及实例代码(一)
2017/01/08 Javascript
详解angularJS自定义指令间的相互交互
2017/07/05 Javascript
JS实现调用本地摄像头功能示例
2018/05/18 Javascript
Echart折线图手柄触发事件示例详解
2018/12/16 Javascript
原生JS实现逼真的图片3D旋转效果详解
2019/02/16 Javascript
js module大战
2019/04/19 Javascript
vue中keep-alive内置组件缓存的实例代码
2020/04/16 Javascript
python中关于日期时间处理的问答集锦
2013/03/08 Python
python机器学习之神经网络(二)
2017/12/20 Python
python实现生命游戏的示例代码(Game of Life)
2018/01/24 Python
Python之list对应元素求和的方法
2018/06/28 Python
Python单元测试简单示例
2018/07/03 Python
python3安装crypto出错及解决方法
2019/07/30 Python
numpy.linalg.eig() 计算矩阵特征向量方式
2019/11/29 Python
如何在mac环境中用python处理protobuf
2019/12/25 Python
python开发一个解析protobuf文件的简单编译器
2020/11/17 Python
Gloeilampgoedkoop荷兰:在线购买灯泡
2019/02/16 全球购物
信号量和自旋锁的区别?如何选择使用?
2015/09/08 面试题
模具设计与制造专业推荐信
2014/02/16 职场文书
班子群众路线教育实践个人对照检查材料思想汇报
2014/09/30 职场文书
井冈山红色之旅感想
2014/10/07 职场文书
企业廉洁教育心得体会
2016/01/20 职场文书
你喜欢篮球吗?Python实现篮球游戏
2021/06/11 Python