原生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 相关文章推荐
jquery tools 系列 scrollable(2)
Sep 06 Javascript
做好七件事帮你提升jQuery的性能
Feb 06 Javascript
JS案例分享之金额小写转大写
May 15 Javascript
JS实现左右拖动改变内容显示区域大小的方法
Oct 13 Javascript
理解Javascript图片预加载
Feb 23 Javascript
JavaScript闭包实例详解
Jun 03 Javascript
Vue.js快速入门实例教程
Oct 15 Javascript
js中split()方法得到的数组长度问题
Jul 19 Javascript
Vue Cli3 创建项目的方法步骤
Oct 15 Javascript
Cordova(ionic)项目实现双击返回键退出应用
Sep 17 Javascript
js回调函数仿360开机
Dec 26 Javascript
React配置子路由的实现
Jun 03 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的网址
2006/11/25 PHP
PHP内核介绍及扩展开发指南―基础知识
2011/09/11 PHP
php读取mysql中文数据出现乱码的解决方法
2013/08/16 PHP
PHP将回调函数作用到给定数组单元的方法
2014/08/19 PHP
thinkPHP5.0框架模块设计详解
2017/03/18 PHP
jQuery 常见学习网站与参考书
2009/11/09 Javascript
Javascript 页面模板化很多人没有使用过的方法
2012/06/05 Javascript
jquery中加载图片自适应大小主要实现代码
2013/08/23 Javascript
js showModalDialog参数的使用详解
2014/01/07 Javascript
jQuery插件实现大图全屏图片相册
2015/03/14 Javascript
AngularJS入门教程之AngularJS指令
2016/04/18 Javascript
Node.js获取前端ajax提交的request信息
2017/02/20 Javascript
Vue.js仿Metronic高级表格(一)静态设计
2017/04/17 Javascript
JS基于正则实现数字千分位用逗号分隔的方法
2017/06/16 Javascript
纯JavaScript实现实时反馈系统时间
2017/10/26 Javascript
vue鼠标悬停事件实例详解
2019/04/01 Javascript
原生js实现trigger方法示例代码
2019/05/22 Javascript
vue 路由懒加载中给 Webpack Chunks 命名的方法
2020/04/24 Javascript
JavaScript中遍历的十种方法总结
2020/12/15 Javascript
python快速查找算法应用实例
2014/09/26 Python
使用Python判断质数(素数)的简单方法讲解
2016/05/05 Python
基于tensorflow加载部分层的方法
2018/07/26 Python
Python下opencv图像阈值处理的使用笔记
2019/08/04 Python
感知器基础原理及python实现过程详解
2019/09/30 Python
浅析python,PyCharm,Anaconda三者之间的关系
2019/11/27 Python
Django 路由层URLconf的实现
2019/12/30 Python
使用python执行shell脚本 并动态传参 及subprocess的使用详解
2020/03/06 Python
教你使用Sublime text3搭建Python开发环境及常用插件安装另分享Sublime text3最新激活注册码
2020/11/12 Python
Python join()函数原理及使用方法
2020/11/14 Python
宏碁西班牙官网:Acer西班牙
2021/01/08 全球购物
幼教毕业生自我鉴定
2014/01/12 职场文书
整改报告怎么写
2014/11/06 职场文书
家庭聚会祝酒词
2015/08/11 职场文书
Python趣味实战之手把手教你实现举牌小人生成器
2021/06/07 Python
每日六道java新手入门面试题,通往自由的道路
2021/06/30 Java/Android
win7配置本地ftp服务器的图文教程
2022/08/05 Servers