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