标签:
一直从事于后端编程工作,工作中也经常接触和使用一些前段技术,但大多数还是用于操作和控制数据与客户端交互工作。随着互联网技术的发展以及硬件性能的不断提升,人们对于交互式体验已变得越来越重视,进而前端技术已经越来越突显出它的重要性,特别是一些炫酷的特效,精美的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.cubHidth = opts.cubHidth || 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; 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 width: this.cubWidth, 172 height: this.cubHidth, 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, cubHidth: 100, marginLeft: 10, marginTop: 10, marginZ: 10, cubZ: 100 }); 640 </script> 641 642 </body> 643 </html>
注:在此基础上可以加上鼠标控制事件,可以直接通过鼠标控制器任意方向的旋扭,也可以稍加改进用于炫酷展示图片!后续有时间我将加上这些功能,与大家再次分享!
用纯原生态javascript+css3 写的3D魔方动画旋扭特效
标签:
原文地址:http://www.cnblogs.com/linbl/p/5276028.html