Home  >  Article  >  Web Front-end  >  3D Rubik's Cube animation twisting special effects written in native javascript+css3_javascript skills

3D Rubik's Cube animation twisting special effects written in native javascript+css3_javascript skills

WBOY
WBOYOriginal
2016-05-16 15:10:461990browse

I have been engaged in back-end programming work, and I often come into contact with and use some front-end technologies in my work, but most of them are used to operate and control data and interact with clients. With the development of Internet technology and the continuous improvement of hardware performance, people have paid more and more attention to interactive experience, and front-end technology has increasingly highlighted its importance, especially some cool special effects, exquisite The UI design is eye-catching, and I immediately feel that the website platform is much taller, very eye-catching, and gives people a good visual impact. Especially the current updates of CSS3 and HTML5 technology make it possible to use smaller These effects can be easily achieved at a reasonable price. Therefore, I immediately worshiped the front-end technology, became interested in leisurely, and was eager to try it. I randomly used the new 3D special effects technology and animation special effects function of CSS3 and added original javascript to write a Rubik's cube that randomly twists and turns. , after the specified number of steps, the Rubik's Cube will return to its original position according to the recorded action and the reverse twist. I will publish it immediately to share with everyone. I also hope that the front-end experts can give me some advice. Thank you very much!

The code is as follows:

<!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 == "" &#63; "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 == "" &#63; "" : "-" + 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 == "" &#63; "" : "-" + 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)\/&#63;\s*(\.&#63;\d+(\.\d+)*)/i);
     if (M && (tem = ua.match(/version\/([\.\d]+)/i)) != null) M[2] = tem[1];
     M = M &#63; [M[1], M[2]] : [N, navigator.appVersion, '-&#63;'];
     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>

Note: On this basis, you can add mouse control events, you can directly turn the mouse controller in any direction, or you can slightly improve it to display cool pictures! I will add these functions when I have time and share them with you again!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn