• 用纯原生态javascript+css3 写的3D魔方动画旋扭特效


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

    代码如下:
      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      5     <title></title>
      6     <meta charset="utf-8" />
      7     <script language="javascript" type="text/javascript">
      8         var cache = {};
      9         (function (exports) {
     10 
     11             function Cube(opts) {
     12                 opts = opts || {};
     13                 this.parent = opts.parent; //插入到哪里
     14                 this.browserPrefix = opts.browserPrefix;
     15                 this.width = opts.width;
     16                 this.height = opts.height;
     17                 this.cubZ = opts.cubZ;
     18                 this.face = opts.face;
     19                 this.row = opts.row;
     20                 this.column = opts.column;
     21                 this.offsetX = this.column * (this.width + opts.marginX); //
     22                 this.offsetY = this.row * (this.height + opts.marginY);//
     23                 this.offsetZ = this.face * (this.cubZ + opts.marginZ);//
     24                 this.positiveZ = this.cubZ / 2;
     25                 this.negativeZ = -this.cubZ / 2;
     26                 this.cubFaceInfo = opts.cubFaceInfo;
     27                 this.dimension = opts.dimension;
     28                 this.centerX = (this.dimension * this.width + (this.dimension - 1) * opts.marginX) / 2;
     29                 this.centerY = (this.dimension * this.height + (this.dimension - 1) * opts.marginY) / 2;
     30                 this.centerZ = (this.dimension * this.cubZ + (this.dimension - 1) * opts.marginZ) / 2;
     31                 this.translateX = this.offsetX - this.centerX; //把中心点设为原点
     32                 this.translateY = this.offsetY - this.centerY; //
     33                 this.translateZ = this.cubZ / 2 + this.offsetZ - this.centerZ; //offsetZ按上面计算应该跟x,y在一个平面上即后面,但实际上由于要形成立方体,在Z轴上已经后退了cubZ/2个距离,故为和上面保持一致在一个面上,这里需要再加回cubZ/2个距离,使默认的xyz原点都在一个平面上即立方体后面左上角三维坐标系,以这个点作为参考点平移和设置旋转原点
     34                 this.cubeFace = [];
     35                 this.rotateTransfrom = "";
     36                 this.init();
     37 
     38             }
     39             Cube.prototype = {
     40                 init: function () {
     41                     this.createCubeBox();
     42                     this.createFront();
     43                     this.createBack();
     44                     this.createTop();
     45                     this.createBottom();
     46                     this.createLeft();
     47                     this.createRight();
     48 
     49                 },
     50                 createCubeBox: function () {
     51                     this.Box = document.createElement('div');
     52                     this.Box.style.width = this.width + "px";
     53                     this.Box.style.height = this.height + "px";
     54                     this.Box.style.left = "50%";
     55                     this.Box.style.top = "50%";
     56                     this.Box.style.position = "absolute";
     57                     this.Box.style[this.browserPrefix + "TransformStyle"] = "preserve-3d";
     58                     this.Box.style[this.browserPrefix + "Perspective"] = "0";
     59                     //                    this.Scene.style[this.browserPrefix + "backfaceVisibility"] = "hidden";
     60                     this.intalTransform = "translateZ(" + this.translateZ + "px) translateX(" + this.translateX + "px) translateY(" + this.translateY + "px)";
     61                     this.Box.style[this.browserPrefix + "Transform"] = this.intalTransform;
     62                     this.Box.style[this.browserPrefix + "TransformOrigin"] = "" + (-this.translateX) + "px " + (-this.translateY) + "px " + (-this.translateZ) + "px";
     63                     this.parent.appendChild(this.Box);
     64                     this.x = window.getComputedStyle(this.Box).getPropertyValue('left');
     65                     this.y = window.getComputedStyle(this.Box).getPropertyValue('top');
     66                     this.matrix3d = window.getComputedStyle(this.Box).getPropertyValue('transform');
     67                 },
     68                 createFace: function () {
     69                     var face = document.createElement('div');
     70                     face.style.margin = 0;
     71                     face.style.position = "absolute";
     72                     face.style.width = this.width + "px";
     73                     face.style.height = this.height + "px";
     74                     return face;
     75                 },
     76                 createFront: function () {
     77                     var face = this.createFace();
     78                     face.style[this.browserPrefix + "Transform"] = "translateZ(" + this.positiveZ + "px) "
     79                     this.cubeFace.push(face);
     80                     this.front = face;
     81                     this.Box.appendChild(face);
     82                 },
     83                 createBack: function () {
     84                     var face = this.createFace();
     85                     face.style[this.browserPrefix + "Transform"] = "translateZ(" + this.negativeZ + "px) ";
     86                     this.cubeFace.push(face);
     87                     this.back = face;
     88                     this.Box.appendChild(face);
     89                 },
     90                 createTop: function () {
     91                     var face = this.createFace();
     92                     face.style[this.browserPrefix + "Transform"] = "rotateX(90deg) translateZ(" + this.positiveZ + "px) ";
     93                     this.cubeFace.push(face);
     94                     this.top = face;
     95                     this.Box.appendChild(face);
     96                 },
     97                 createBottom: function () {
     98                     var face = this.createFace();
     99                     face.style[this.browserPrefix + "Transform"] = "rotateX(90deg) translateZ(" + this.negativeZ + "px) ";
    100                     this.cubeFace.push(face);
    101                     this.bottom = face;
    102                     this.Box.appendChild(face);
    103                 },
    104                 createLeft: function () {
    105                     var face = this.createFace();
    106                     face.style[this.browserPrefix + "Transform"] = "rotateY(90deg) translateZ(" + this.negativeZ + "px) ";
    107                     this.cubeFace.push(face);
    108                     this.left = face;
    109                     this.Box.appendChild(face);
    110                 },
    111                 createRight: function () {
    112                     var face = this.createFace();
    113                     face.style[this.browserPrefix + "Transform"] = "rotateY(90deg) translateZ(" + (this.positiveZ) + "px) ";
    114                     this.cubeFace.push(face);
    115                     this.right = face;
    116                     this.Box.appendChild(face);
    117                 }
    118 
    119             }
    120             exports.magicCube = function (opts) {
    121                 opts = opts || {};
    122                 this.parent = opts.parent || document.getElementsByTagName('body')[0];
    123                 this.dimension = opts.dimension || 3;  //魔方级数
    124                 this.cubWidth = opts.cubWidth || 50;   //单个立方体宽度
    125                 this.cubHeight = opts.cubHeight || 50; //单个立方体高度
    126                 this.marginLeft = opts.marginLeft || 0;//水平方向间距
    127                 this.marginTop = opts.marginLeft || 0; //上下方向间距
    128                 this.marginZ = opts.marginZ || 0;      //前后方向间距
    129                 this.cubZ = opts.cubZ || 50;           //单个立方体Z轴距离
    130                 this.sceneWidth = opts.sceneWidth;     //3d场景宽度
    131                 this.sceneHeight = opts.sceneHeight;   //3d场景高度
    132                 this.Perspective = opts.Perspective || 0; //投影值
    133                 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)" } }; //立方体面信息
    134                 this.angle = opts.angle || 90;         //转动的角度
    135                 this.rollbackPoint = opts.rollbackPoint || 10;//回滚的步数
    136                 this.faceCount = this.dimension * this.dimension; //每面立方体个数
    137                 this.count = this.dimension * this.dimension * this.dimension; //立方体总个数
    138                 this.cubes = [];
    139                 this.browserPrefix = "";
    140                 this.isRunning = 0;
    141                 this.timer = null;
    142                 this.rotateFace;//转动的3维坐标系方向
    143                 this.moveDirect = true;//正向随机动作还是回归,默认为正向
    144                 this.cubeMoveQueue = [];
    145                 this.rollMoveStack = [];//动作回归的堆栈
    146                 this.init();
    147             };
    148             magicCube.prototype = {
    149                 init: function () {
    150                     this.start();
    151                 },
    152                 create3dScene: function () {
    153                     this.Scene = document.createElement('div');
    154                     //this.Scene.className = "cube";
    155                     var width = this.sceneWidth || this.clientWidth,
    156                         height = this.sceneHeight || this.clientHeight;
    157                     this.Scene.style.width = width + "px";
    158                     this.Scene.style.height = height + "px";
    159                     this.Scene.style.position = "relative";
    160                     this.Scene.style[this.browserPrefix + "TransformStyle"] = "preserve-3d";
    161                     this.Scene.style[this.browserPrefix + "Perspective"] = this.Perspective + "px";
    162                     //                    this.Scene.style[this.browserPrefix + "backfaceVisibility"] = "hidden";
    163                     this.Scene.style[this.browserPrefix + "Transform"] = "rotateX(-30deg) rotateY(30deg) ";
    164                     this.parent.appendChild(this.Scene);
    165 
    166                 },
    167                 create: function (face, row, column) {
    168                     return new Cube({
    169                         parent: this.Scene,
    170                         dimension: this.dimension,
    171                          this.cubWidth,
    172                         height: this.cubHeight,
    173                         cubZ: this.cubZ,
    174                         face: face,
    175                         row: row,
    176                         column: column,
    177                         browserPrefix: this.browserPrefix,
    178                         cubFaceInfo: this.cubFaceInfo,
    179                         marginX: this.marginLeft,
    180                         marginY: this.marginTop,
    181                         marginZ: this.marginZ,
    182                         dimension: this.dimension
    183                     });
    184                 },
    185                 createMagicCube: function (index) {
    186                     var face = 0, row = 0, column = 0;
    187                     for (var i = 0; i < this.count; i++) {
    188                         this.cubes.push(this.create(face, row, column));
    189                         this.cubes[this.cubes.length - 1].index = this.cubes.length - 1;
    190                         column++;
    191                         if ((i + 1) % this.dimension === 0) {
    192                             row++;
    193                             column = 0;
    194                         }
    195                         if ((i + 1) % this.faceCount === 0) {
    196                             face++;
    197                             row = 0;
    198                         }
    199                     }
    200                 },
    201                 drawBackGroundColor: function () {
    202                     for (var face in this.cubFaceInfo) {
    203                         if (face == "inner") {
    204                             this.setInnerBKColor(this.cubFaceInfo[face].backGround);
    205                         }
    206                         else {
    207                             var cube = this.getCubesByFace(face);
    208                             for (var i = 0, len = cube.length; i < len; i++) {
    209                                 cube[i][face].style.background = this.cubFaceInfo[face].backGround;
    210                             }
    211                         }
    212                     }
    213 
    214                 },
    215                 setInnerBKColor: function (color) {
    216                     for (var i = 0; i < this.count; i++) {
    217                         for (var j = 0; j < 6; j++) {
    218                             if (this.cubes[i].cubeFace[j].style.background == "") {
    219                                 this.cubes[i].cubeFace[j].style.background = color;
    220                             }
    221                         }
    222                     }
    223                 },
    224                 getZFace: function (zIndex) {
    225                     var zFace = [];
    226                     if (zIndex < 1 || zIndex > this.dimension)
    227                         return null;
    228                     for (var i = (zIndex - 1) * this.faceCount; i < zIndex * this.faceCount; i++) {
    229                         zFace.push(this.cubes[i]);
    230                     }
    231                     return zFace;
    232                 },
    233                 getXFace: function (xIndex) {
    234                     var xFace = [];
    235                     if (xIndex < 1 || xIndex > this.dimension)
    236                         return null;
    237                     for (var i = 0; i < this.count; i++) {
    238                         if (i % this.dimension == 0)
    239                             xFace.push(this.cubes[i + xIndex - 1]);
    240                     }
    241                     return xFace;
    242                 },
    243                 getYFace: function (yIndex) {
    244                     var yFace = [];
    245                     if (yIndex < 1 || yIndex > this.dimension)
    246                         return null;
    247                     for (var i = 0; i < this.count; i++) {
    248                         if (i % this.faceCount == (yIndex - 1) * this.dimension) {
    249                             for (var j = 0; j < this.dimension; j++)
    250                                 yFace.push(this.cubes[i + j]);
    251                         }
    252                     }
    253                     return yFace;
    254                 },
    255                 getSideCubes: function (cubes, circleIndex) {
    256                     var sides = [], top = [], left = [], bottom = [], right = [];
    257                     if (circleIndex < 0 || circleIndex > this.dimension / 2 - 1)
    258                         return null;
    259                     for (var i = 0, count = this.dimension - circleIndex * 2; i < count; i++) {
    260                         top.push(cubes[circleIndex * this.dimension + circleIndex + i]);
    261                         left.push(cubes[circleIndex * this.dimension + circleIndex + i * this.dimension]);
    262                         bottom.push(cubes[(this.dimension - 1 - circleIndex) * this.dimension + circleIndex + i]);
    263                         right.push(cubes[circleIndex * this.dimension + circleIndex + i * this.dimension + (this.dimension - (circleIndex * 2) - 1)]);
    264                     }
    265                     sides.push(this.orderByDesc(top));
    266                     sides.push(left);
    267                     sides.push(bottom);
    268                     sides.push(this.orderByDesc(right));
    269                     return sides;
    270                 },
    271 
    272                 getCubesByFace: function (face) {
    273                     switch (face) {
    274                         case "front": return this.getZFace(this.dimension);
    275                         case "back": return this.getZFace(1);
    276                         case "left": return this.getXFace(1);
    277                         case "right": return this.getXFace(this.dimension);
    278                         case "top": return this.getYFace(1);
    279                         case "bottom": return this.getYFace(this.dimension);
    280                     }
    281                 },
    282                 moveMagicCube: function () {
    283                     if (this.cubes.length < 1) return;
    284                     //var cubes = this.getYFace(2);
    285                     //for (var i = 0, len = cubes.length; i < len; i++) {
    286                     //    cubes[i].Box.className = "rotate";
    287                     //}
    288                     //随机产生3D转动方向
    289                     this.isRunning = 0;
    290                     var direct = this.random(1, 3), rotateDirect = "", getFaceFun;
    291                     //  direct=3;
    292                     switch (direct) {
    293                         case 1: rotateDirect = "rotateX"; getFaceFun = this.getXFace; break;
    294                         case 2: rotateDirect = "rotateY"; getFaceFun = this.getYFace; break;
    295                         case 3: rotateDirect = "rotateZ"; getFaceFun = this.getZFace; break;
    296                     }
    297                     this.rotateFace = rotateDirect;
    298                     this.cubeRotateStatus = [];
    299                     for (var i = 1; i <= this.dimension; i++) {
    300                         var status = this.random(0, 2);
    301                         this.cubeRotateStatus.push(status);
    302                         switch (status) {
    303                             case 0: break;//不转动
    304                             case 1: this.rotateBox(this.angle, rotateDirect, i, getFaceFun.call(this, i)); break;//正向转动90
    305                             case 2: this.rotateBox(-this.angle, rotateDirect, i, getFaceFun.call(this, i)); break;//反向转动90
    306                         }
    307 
    308                     }
    309 
    310                     var flag = false;
    311                     for (var i = 0, len = this.cubeRotateStatus.length; i < len; i++) {
    312                         if (this.cubeRotateStatus[i]) {
    313                             flag = true;
    314                             break;
    315                         }
    316                     }
    317                     if (!flag) {//一个都没转的情况 则强制补充一个
    318                         var index = this.random(1, this.dimension);
    319                         this.rotateBox(this.angle, rotateDirect, index, getFaceFun.call(this, index)); //正向转动90
    320                         this.cubeRotateStatus[index - 1] = 1;//全都不转动 默认选出一个 使其正向转动指定度数
    321                     }
    322                     setTimeout(this.timerFun, 100);
    323                     this.rollMoveStack.push({ rotateFace: this.rotateFace, cubeRotateStatus: this.cubeRotateStatus });//记录动作状态
    324                     if (this.rollMoveStack.length == this.rollbackPoint)//判断当达到阀值时切换动作方向为回归
    325                         this.moveDirect = false;
    326 
    327                 },
    328                 moveRollBackCube: function () {
    329                     var record = this.rollMoveStack.pop(), getFaceFun;
    330                     this.rotateFace = record.rotateFace;
    331                     this.isRunning = 0;
    332                     switch (record.rotateFace) {
    333                         case "rotateX": getFaceFun = this.getXFace; break;
    334                         case "rotateY": getFaceFun = this.getYFace; break;
    335                         case "rotateZ": getFaceFun = this.getZFace; break;
    336                     }
    337                     this.cubeRotateStatus = [];
    338                     for (var i = 0, len = record.cubeRotateStatus.length; i < len; i++) {
    339                         var dimensionIndex =  i+1, status = record.cubeRotateStatus[i];
    340                         if (status == 1) {
    341                             this.cubeRotateStatus.push(2);//1 变2,2变1
    342                             this.rotateBox(-this.angle, record.rotateFace, dimensionIndex, getFaceFun.call(this, dimensionIndex)); //反向转动90
    343                         }
    344                         else if (status == 2) {
    345                             this.cubeRotateStatus.push(1);//1 变2,2变1
    346                             this.rotateBox(this.angle, record.rotateFace, dimensionIndex, getFaceFun.call(this, dimensionIndex)); //反向转动90
    347                         }
    348                         else {
    349                             this.cubeRotateStatus.push(0);
    350                         }
    351                     }
    352                     setTimeout(this.timerFun, 100);
    353                     if (this.rollMoveStack.length == 0)//判断当达到0时切换动作为正向随机
    354                         this.moveDirect = true;
    355                 },
    356                 intersect: function (source, target) {
    357                     var data = [];
    358                     for (var i = 0, len = source.length; i < len; i++) {
    359                         var index = target.indexOf(source[i]);
    360                         if (index >= 0)
    361                             data.push(source[i])
    362                     }
    363                     return data;
    364                 },
    365                 orderByDesc: function (datas) {
    366                     var temp;
    367                     for (var i = 0; i < datas.length - 1; i++) {
    368                         for (var j = i + 1; j < datas.length; j++) {
    369                             if (parseFloat(datas[i].index) < parseFloat(datas[j].index)) {
    370                                 temp = datas[i];
    371                                 datas[i] = datas[j];
    372                                 datas[j] = temp;
    373                             }
    374                         }
    375                     }
    376                     return datas;
    377                 },
    378                 getSideBackGround: function (sideFaces, face) {
    379                     var backGrounds = [];
    380                     for (var i = 0, len = sideFaces.length; i < len; i++) {
    381                         backGrounds.push(sideFaces[i][face].style.background);
    382                     }
    383                     return backGrounds;
    384                 },
    385                 setRotateDirectSideBackGround: function (faceCubes, sideFace, offset, status) {
    386                     var oldSides = this.getSideCubes(faceCubes, 0), backColor = [];
    387                     var offsetNIndex, offsetPIndex;
    388                     for (var j = 0; j < 4; j++) {
    389                         offsetPIndex = (j - offset + 4) % 4;
    390                         offsetNIndex = (j + offset) % 4;
    391                         if (this.rotateFace == "rotateY") {
    392                             if (status == 1)//正向
    393                             {
    394                                 backColor[j] = this.getSideBackGround(oldSides[offsetPIndex], sideFace[offsetPIndex]);
    395                             }
    396                             else//反向
    397                             {
    398                                 backColor[j] = this.getSideBackGround(oldSides[offsetNIndex], sideFace[offsetNIndex]);
    399                             }
    400                         }
    401                         else {
    402                             if (status == 2)//正向
    403                             {
    404                                 backColor[j] = this.getSideBackGround(oldSides[offsetPIndex], sideFace[offsetPIndex]);
    405                             }
    406                             else//反向
    407                             {
    408                                 backColor[j] = this.getSideBackGround(oldSides[offsetNIndex], sideFace[offsetNIndex]);
    409                             }
    410                         }
    411 
    412                     }
    413                     for (var j = 0; j < 4; j++) {
    414                         for (var k = 0; k < oldSides[j].length; k++) {
    415                             oldSides[j][k][sideFace[j]].style.background = backColor[j][k];
    416                         }
    417                     }
    418                 },
    419                 setRotateOtherDirectSideBackGround: function (faceCubes, otherFace, offset, status) {
    420                     var oldSides = [], backColor = [];
    421                     var offsetNIndex, offsetPIndex;
    422                     for (var i = 0; i <= parseInt(this.dimension / 2) - 1; i++) {
    423                         oldSides = this.getSideCubes(faceCubes, i), backColor = [];
    424                         for (var j = 0; j < 4; j++) {
    425                             offsetPIndex = (j - offset + 4) % 4;
    426                             offsetNIndex = (j + offset) % 4;
    427                             if (this.rotateFace == "rotateY") {
    428                                 if (status == 1)//正向
    429                                 {
    430                                     backColor[j] = this.getSideBackGround(oldSides[offsetPIndex], otherFace);
    431                                 }
    432                                 else//反向
    433                                 {
    434                                     backColor[j] = this.getSideBackGround(oldSides[offsetNIndex], otherFace);
    435                                 }
    436                             }
    437                             else {
    438                                 if (status == 2)//正向
    439                                 {
    440                                     backColor[j] = this.getSideBackGround(oldSides[offsetPIndex], otherFace);
    441                                 }
    442                                 else//反向
    443                                 {
    444                                     backColor[j] = this.getSideBackGround(oldSides[offsetNIndex], otherFace);
    445                                 }
    446                             }
    447 
    448                         }
    449                         for (var j = 0; j < 4; j++) {
    450                             for (var k = 0; k < oldSides[j].length; k++) {
    451                                 oldSides[j][k][otherFace].style.background = backColor[j][k];
    452                             }
    453                         }
    454                     }
    455 
    456                 },
    457                 animationEnd: function () {
    458                     var offset = this.angle / 90, faceCubes = [], otherFace;
    459                     var zSideFace = ["top", "left", "bottom", "right"], xSideFace = ["back", "top", "front", "bottom"], ySideFace = ["back", "left", "front", "right"], sideFace = [];
    460                     for (var i = 0, len = this.cubeRotateStatus.length; i < len; i++) {
    461                         var status = this.cubeRotateStatus[i];
    462                         if (status) {
    463                             var dimensionIndex = i + 1;
    464                             switch (this.rotateFace) {
    465                                 case "rotateX": faceCubes = this.getXFace(dimensionIndex); sideFace = xSideFace; if (dimensionIndex == 1) otherFace = "left"; else if (dimensionIndex == this.dimension) otherFace = "right"; break;
    466                                 case "rotateY": faceCubes = this.getYFace(dimensionIndex); sideFace = ySideFace; if (dimensionIndex == 1) otherFace = "top"; else if (dimensionIndex == this.dimension) otherFace = "bottom"; break;
    467                                 case "rotateZ": faceCubes = this.getZFace(dimensionIndex); sideFace = zSideFace; if (dimensionIndex == 1) otherFace = "back"; else if (dimensionIndex == this.dimension) otherFace = "front"; break;
    468                             }
    469                             this.setRotateDirectSideBackGround(faceCubes, sideFace, offset, status);
    470                             if (dimensionIndex == 1 || dimensionIndex == this.dimension)
    471                                 this.setRotateOtherDirectSideBackGround(faceCubes, otherFace, offset, status);
    472                         }
    473 
    474                     }
    475                   //  console.info(this.rollMoveStack.length + "," + this.moveDirect);
    476                     if (this.moveDirect)
    477                         this.moveMagicCube();
    478                     else
    479                         this.moveRollBackCube();
    480                     // alert("运行结束");
    481                 },
    482                 bindAnimationEvent: function () {
    483                     var loopMove = function () {
    484                         cache.magicCube.isRunning--;//由于按组转动,顾要等组成员都完成再进行新的动画
    485                         if (cache.magicCube.isRunning == 0)
    486                             cache.magicCube.animationEnd();
    487                     }
    488                     for (var i = 0; i < this.count; i++) {
    489 
    490                         this.prefixedEvent(this.cubes[i].Box, "AnimationEnd", loopMove, true);
    491                     }
    492                     cache.magicCube = this;//缓存,避免内存泄露
    493                 },
    494                 rotateBox: function (angle, rotateDirect, faceIndex, cubes) {
    495                     if (cubes != null) {
    496                         var startStatus = rotateDirect + "(0deg)", endStatus = rotateDirect + "(" + angle + "deg)";
    497                         // this.changeAnimationStatus("mydhua", startStatus, endStatus)
    498                         for (var i = 0, len = cubes.length; i < len; i++) {
    499                             var ruleName = "roateRule" + faceIndex + i;
    500                             this.isRunning++;//组成员转动统计
    501                             //if (cubes[i].rotateTransfrom != "")
    502                             //    startStatus = cubes[i].rotateTransfrom;
    503                             cubes[i].rotateTransfrom = endStatus;
    504                             if (this.findKeyframesRule(ruleName) == null)
    505                                 this.createKeyframesRule(ruleName, cubes[i].intalTransform + " " + startStatus, cubes[i].intalTransform + " " + endStatus);
    506                             else
    507                                 this.changeAnimationStatus(ruleName, cubes[i].intalTransform + " " + startStatus, cubes[i].intalTransform + " " + endStatus);
    508                             cubes[i].Box.style[this.browserPrefix + "AnimationName"] = "none";
    509                             this.cubeMoveQueue.push({ cube: cubes[i], rule: ruleName });
    510                         }
    511                     }
    512                 },
    513                 findKeyframesRule: function (rule) {
    514                     var ruleName = this.browserPrefix == "" ? "KEYFRAMES_RULE" : this.browserPrefix.toUpperCase() + "_KEYFRAMES_RULE";
    515                     var ss = document.styleSheets;
    516                     for (var i = 0; i < ss.length; ++i) {
    517                         for (var j = 0; j < ss[i].cssRules.length; ++j) {
    518                             if (ss[i].cssRules[j].type == window.CSSRule[ruleName] && ss[i].cssRules[j].name == rule) { return ss[i].cssRules[j]; }
    519                         }
    520                     }
    521                     return null;
    522                 },
    523                 createKeyframesRule: function (rule, startStatus, endStatus) {
    524                     var prefix = this.browserPrefix == "" ? "" : "-" + this.browserPrefix + "-";
    525                     var sheet;
    526                     if (document.styleSheets.length < 1)
    527                         sheet = this.createSheets();
    528                     else
    529                         sheet = document.styleSheets[0];
    530                     var selectorText = "@" + prefix + "keyframes " + rule;
    531                     var cssText = "0% { " + prefix + "transform: " + startStatus + "; } 100% { " + prefix + "transform: " + endStatus + "; }"
    532                     if (sheet.insertRule) {
    533                         sheet.insertRule(selectorText + "{" + cssText + "}", 0);
    534                     } else if (sheet.addRule) {//兼容IE
    535                         sheet.addRule(selectorText, cssText, 0);
    536                     }
    537                 },
    538                 removeKeyframeRule: function (keyframes) {
    539                     var length = keyframes.cssRules.length;
    540                     var keyframeString = [];
    541                     for (var i = 0; i < length; i++) {
    542                         keyframeString.push(keyframes.cssRules[i].keyText);
    543                     }
    544                     //移除动画帧规则
    545                     for (var i = 0, j = length; i < j; i++) {
    546                         if (this.browserPrefix == "webkit" || this.browserPrefix == "Moz")
    547                             keyframes.deleteRule(keyframeString[i]);
    548                         else
    549                             keyframes.deleteRule(i); //兼容IE
    550                     }
    551                 },
    552                 changeAnimationStatus: function (animationName, startStatus, endStatus) {
    553                     var keyframes = this.findKeyframesRule(animationName);
    554                     this.removeKeyframeRule(keyframes);
    555                     //重新设置帧规则
    556                     var prefix = this.browserPrefix == "" ? "" : "-" + this.browserPrefix + "-";
    557                     keyframes.appendRule("0% { " + prefix + "transform: " + startStatus + "; }");
    558                     keyframes.appendRule("100% { " + prefix + "transform: " + endStatus + "; }");
    559                 },
    560                 createSheets: function () {
    561                     // 创建 <style> 标签
    562                     var style = document.createElement("style");
    563                     // 可以添加一个媒体(/媒体查询,media query)属性
    564                     // style.setAttribute("media", "screen")
    565                     // style.setAttribute("media", "only screen and (max-width : 1024px)")
    566                     // 对WebKit hack :(
    567                     style.appendChild(document.createTextNode(""));
    568                     // 将 <style> 元素加到页面中
    569                     document.head.appendChild(style);
    570                     return style.sheet;
    571                 },
    572                 prefixedEvent: function (element, type, callback, isAdd) {
    573                     var pfx = ["webkit", "moz", "MS", "o", ""];
    574                     for (var p = 0; p < pfx.length; p++) {
    575                         if (!pfx[p]) type = type.toLowerCase();
    576                         if (isAdd)
    577                             element.addEventListener(pfx[p] + type, callback, false);
    578                         else
    579                             element.removeEventListener(pfx[p] + type, callback, false);
    580                     }
    581                 },
    582                 start: function () {
    583                     this.css();
    584                     this.prefix();
    585                     this.create3dScene();
    586                     this.createMagicCube();
    587                     this.drawBackGroundColor();
    588                     this.bindAnimationEvent();//绑定动画播放完成事件
    589                     this.moveMagicCube();     //立即开始动画
    590                     // this.timer = setInterval(this.timerFun, 100);
    591                 },
    592                 timerFun: function () {
    593                     var _this = cache.magicCube;
    594                     if (_this.isRunning >= _this.dimension) {
    595                         for (var i = 0, len = _this.cubeMoveQueue.length; i < len; i++) {
    596                             var animation = _this.cubeMoveQueue.shift();
    597                             animation.cube.Box.style[_this.browserPrefix + "Animation"] = animation.rule + " 2s linear 1"; // Chrome, Safari 和 Opera 代码
    598                         }
    599 
    600                     }
    601 
    602                 },
    603                 css: function () {
    604                     var d = document,
    605                         doc = d.documentElement,
    606                         body = d.body;
    607                     this.clientWidth = doc.clientWidth;
    608                     this.clientHeight = doc.clientHeight;
    609                     if (d.compatMode != "CSS1Compat") {
    610                         this.clientWidth = body.clientWidth;
    611                         this.clientHeight = body.clientHeight;
    612                     }
    613                     // console.log(this.width +'////'+ this.height)
    614                 },
    615                 random: function (min, max) {
    616                     return (Math.random() * (max - min + 1) + min) >> 0;
    617                 },
    618                 prefix: function () {
    619                     var N = navigator.appName, ua = navigator.userAgent, tem;
    620                     var M = ua.match(/(opera|chrome|safari|firefox|msie)/?s*(.?d+(.d+)*)/i);
    621                     if (M && (tem = ua.match(/version/([.d]+)/i)) != null) M[2] = tem[1];
    622                     M = M ? [M[1], M[2]] : [N, navigator.appVersion, '-?'];
    623                     M = M[0];
    624                     if (M == "Chrome") { this.browserPrefix = "webkit"; }
    625                     if (M == "Firefox") { this.browserPrefix = "Moz"; }
    626                     if (M == "Safari") { this.browserPrefix = "webkit"; }
    627                     if (M == "MSIE") { this.browserPrefix = "ms"; }
    628                 }
    629 
    630             };
    631         }(window));
    632 
    633 
    634     </script>
    635 
    636 </head>
    637 <body style="background-color:black">
    638     <script>
    639         var cube = new magicCube({ parent: null, dimension: 3, cubWidth: 100, cubHeight: 100, marginLeft: 10, marginTop: 10, marginZ: 10, cubZ: 100 });
    640     </script>
    641 
    642 </body>
    643 </html>
    View Code
    注:在此基础上可以加上鼠标控制事件,可以直接通过鼠标控制器任意方向的旋扭,也可以稍加改进用于炫酷展示图片!后续有时间我将加上这些功能,与大家再次分享!
  • 相关阅读:
    二项式反演
    快速沃尔什变换
    springMVC的form标签
    springMVC的拦截器配置
    RESTful使用方法
    springMVC数据绑定
    使用spring框架自带的字符拦截器
    将idea中的项目上传至github
    springMVC的使用方式
    springMVC的概述
  • 原文地址:https://www.cnblogs.com/linbl/p/5276028.html
Copyright © 2020-2023  润新知