Google Cube立方体
- 发表于
- 前端
几个月前做了个GCube,贴了6张图的立方体,不少人以为是用canvas做的,其实是纯粹的CSS实现。
为了体现是CSS效果,而不是画出来的,现在用iframe替换了图片。这里取了Google的6个服务页面,贴在立方体上,可以实现搜索功能。
增加了滚轮缩放的功能。
Google Cube
<!-- <script src="Cube1.6.1.js"></script> --> <script>// <![CDATA[ /**************************************** * HTML立方体插件 v1.6.1 * By EtherDream (c) 2006-2011 * 最后更新: 2011.1.29 **/ var Cube; (function(){ /******************* * |+y * | * 0----- +x */ * /+z ******************/ function Point(x, y, z) { this.update = function() { this.rx = x; this.ry = y; this.deepth = z; //无限远 }; this.rotate = function(radX, radY, radZ) { var _x, _y, _z; var sin, cos; if(radX) { sin = Math.sin(radX); cos = Math.cos(radX); _y = cos * y - sin * z; _z = cos * z + sin * y; y = _y; z = _z; } if(radY) { sin = Math.sin(radY); cos = Math.cos(radY); _x = cos * x - sin * z; _z = cos * z + sin * x; x = _x; z = _z; } if(radZ) { sin = Math.sin(radZ); cos = Math.cos(radZ); _x = cos * x - sin * y; _y = cos * y + sin * x; x = _x; y = _y; } this.update(); }; this.update(); } /***************************** * p1--------p2 * || * p3--------p4 *****************************/ function Face(P1, P2, P3, P4) { /*************************************************** *P(x,y) + [a,b,c,d,tx,ty] * => P(ax+by+tx, cx+dy+ty) ***************************************************/ this.getMatrix = function() { var tx = P1.rx; var ty = P1.ry; var a = (P2.rx - tx) / 2; var b = (ty - P2.ry) / 2; var c = (P3.rx - tx) / 2; var d = (ty - P3.ry) / 2; return [a, b, c, d, tx, ty]; }; this.getDeepth = function() { return P1.deepth + P4.deepth; }; this.getBlockX = function() { return Math.min(P1.rx, P2.rx, P3.rx, P4.rx); }; this.getBlockY = function() { return Math.max(P1.ry, P2.ry, P3.ry, P4.ry); }; } Cube = function() { /******************* *4-------5 * /|/| *0-------1 | *| | | | *| 7- - -|-6 *|/|/ *3-------2 *******************/ var R = 100; var P = [ new Point(-1, +1, +1), new Point(+1, +1, +1), new Point(+1, -1, +1), new Point(-1, -1, +1), new Point(-1, +1, -1), new Point(+1, +1, -1), new Point(+1, -1, -1), new Point(-1, -1, -1) ]; var F = [ new Face(P[0], P[1], P[3], P[2]), //前 new Face(P[1], P[5], P[2], P[6]), //右 new Face(P[5], P[4], P[6], P[7]), //后 new Face(P[4], P[0], P[7], P[3]), //左 new Face(P[4], P[5], P[0], P[1]), //上 new Face(P[3], P[2], P[7], P[6])//下 ]; var cx, cy; var bLight; var arrInfo = []; var KEY_NAME; var ver = navigator.userAgent; var isIE = /MSIE/.test(ver); var isFF = /Firefox/.test(ver); var RAD = Math.PI / 180; /** * 初始化 */ function Init() { var FILTER_NAME = "DXImageTransform.Microsoft.Matrix"; var div, sty, flt; for(var i=0; i<6; i++) { div = document.createElement("div"); document.body.appendChild(div); sty = div.style; sty.position = "absolute"; sty.background = "#000"; sty.border = "#000 1px solid"; if(isIE) { //IE Filter sty.filter = "progid:" + FILTER_NAME + "(sizingMethod='auto expand')"; flt = div.filters[FILTER_NAME]; } else { //CSS3 transform if(!KEY_NAME) { if(sty.MozTransform != null) //FireFox KEY_NAME = "MozTransform"; else if(sty.WebkitTransform != null) //Chrome,Safari KEY_NAME = "WebkitTransform"; else if(sty.OTransform != null) //Opera KEY_NAME = "OTransform"; else throw new Error("浏览器不支持"); } //调整参照点 sty[KEY_NAME + "Origin"] = "0% 0%"; } arrInfo[i] = {div:div, sty:sty, flt:flt}; } } function setLight(i, val) { var obj = arrInfo[i].fltElem; if(!obj) return; obj.opacity = isIE? val*100: val; } function apply(id, visible, opacity) { var info = arrInfo[id]; var sty = info.sty; if(visible) sty.display = "block"; else return sty.display = "none"; var face = F[id]; var m = face.getMatrix(R); //0.123456 for(var i=0; i<6; i++) m[i] = ((m[i] * 1e6) >> 0) / 1e6; if(isIE) { //IE Matrix滤镜 var flt = info.flt; flt.M11 = m[0]; flt.M21 = m[1]; flt.M12 = m[2]; flt.M22 = m[3]; //flt.Dx = cx + R * m[4]; //flt.Dy = cy - R * m[5]; sty.pixelLeft = cx + R * face.getBlockX(); sty.pixelTop = cy - R * face.getBlockY(); } else { //CSS3 m[4] = cx + R * m[4]; m[5] = cy - R * m[5]; if(isFF) { m[4] += "px"; m[5] += "px"; } sty[KEY_NAME] = "matrix(" + m.join(",") + ")"; } } function draw() { var deepth = []; var z, i; // 深度排序 for(i=0; i<6; i++) deepth[i] = {id:i, val:F[i].getDeepth()}; deepth.sort(function(a,b){return b.val - a.val}); //正面 for(i=0; i<3; i++) { apply(deepth[i].id, true); if(bLight) { z = (deepth[i].val + 2) / 4; setLight(deepth[i].id, z*z); } } //隐面 for(i=3; i<6; i++) apply(deepth[i].id, false); } function updateSize(sty) { var D = Math.round(R+R); if(!isIE) //解决边框分离 D-=2; sty.width = D + "px"; sty.height = D + "px"; } /** * setLocate: * 页面中定位立方体。 * (cx, cy)为立方体中心点坐标 */ this.setLocate = function(_cx, _cy) { cx = _cx; cy = _cy; draw(); }; /** * setFace: * 立方体贴面。 * id: 立方体面编号 * elem: 页面中的HTML元素 */ this.setFace = function(id, elem) { var faceInfo = arrInfo[id]; if(!faceInfo) throw new Error("无效的面ID"); try { if(faceInfo.elem) faceInfo.div.replaceChild(elem, faceInfo.elem); else faceInfo.div.appendChild(elem); //透明度 if(isIE) { elem.style.filter = "alpha"; faceInfo.fltElem = elem.filters["alpha"]; } else { faceInfo.fltElem = elem.style; } faceInfo.elem = elem; } catch(e) { throw new Error("无效的DOM元素"); } }; /** * setRadius: * 设置立方体每个面的半径长度 */ this.setRadius = function(r) { R = r; for(var i=0; i<6; i++) updateSize(arrInfo[i].sty); draw(); }; /** * rotate: * 旋转立方体。 * angleX: 绕X轴旋转angleX角度 * ... */ this.rotate = function(angleX, angleY, angleZ) { for(var i=0; i<8; i++) P[i].rotate(RAD*angleX, RAD*angleY, RAD*angleZ); draw(); }; /** * setLight: * 设置是否开启光亮 */ this.setLight = function(v) { bLight = v; if(!v) for(var i=0; i<6; i++) setLight(i, 0); }; Init(); }; Cube.FACE_FRONT = 0; Cube.FACE_RIGHT = 1; Cube.FACE_BACK = 2; Cube.FACE_LEFT = 3; Cube.FACE_TOP = 4; Cube.FACE_BOTTOM = 5; })() //End Module // ]]></script> <script>// <![CDATA[ /** * Update: 2011-9-2 */ var MyFace = [ { id: Cube.FACE_FRONT, logo: "http://www.google.com.hk/intl/zh-CN/images/logo_cn.png", url: "http://www.google.com/search?q=%s", btn: "Search Web" }, { id: Cube.FACE_BACK, logo: "http://www.google.com.hk/intl/zh-CN_cn/images/logos/images_logo_lg.gif", url: "http://www.google.com/images?q=%s", btn: "Search Image" }, { id: Cube.FACE_LEFT, logo: "http://www.google.com/intl/zh-CN_cn/images/logos/music_logo.gif", url: "http://www.google.cn/music/search?q=%s", btn: "Search Music" }, { id: Cube.FACE_BOTTOM, logo: "http://www.google.com/intl/zh-CN_cn/images/logos/maps_logo.gif", url: "http://maps.google.com/maps?q=%s", btn: "Search Maps" }, { id: Cube.FACE_RIGHT, logo: "http://www.google.com/intl/zh-CN_cn/images/logos/news_logo.gif", url: "http://news.google.com/news/search?q=%s", btn: "Search News" }, { id: Cube.FACE_TOP, logo: "http://www.google.com.hk/intl/zh-CN_cn/images/logos/video_logo_lg.gif", url: "http://video.google.com/search?q=%s", btn: "Search Video" } ]; // ]]></script> <script>// <![CDATA[ var oCube; var cx, cy; var dx, dy; var r = 80; var ar = 0; document.onmousemove = function(e) { e = e || event dx = e.clientX - cx; dy = e.clientY - cy; }; window.onresize = function() { var de = document.documentElement; cx = de.clientWidth / 2; cy = de.clientHeight / 2; oCube.setLocate(cx, cy); }; document.onclick = function(e) { e = e || event; e = e.target || e.srcElement; if(e.tagName == "BUTTON") DoSearch(e); } document.onmouseover = function(e) { e = e || event; e = e.target || e.srcElement; if(e.tagName == "INPUT") e.style.borderColor = "red"; } document.onmouseout = function(e) { e = e || event; e = e.target || e.srcElement; if(e.tagName == "INPUT") e.style.borderColor = "#666"; } document.onkeydown = function(e) { e = e || event; var dom = e.target || e.srcElement; if(dom.tagName == "INPUT" && e.keyCode == 13) DoSearch(dom.nextSibling); } window.onload = function() { var i, oFace; oCube = new Cube(); for(i=0; i<6; i++) { oFace = document.createElement("div"); oFace.className = "face"; oFace.innerHTML = "<img src='" + MyFace[i].logo + "' /><input type='text' /><button tid=" + i + ">" + MyFace[i].btn + "</button>"; document.body.appendChild(oFace); oCube.setFace(MyFace[i].id, oFace); } oCube.setRadius(r); oCube.setLight(true); oCube.rotate(20, 20, 0); setInterval(OnTimer, 16); onresize(); }; var ver = navigator.userAgent; var isIE = /IE/.test(ver); var isFF = /Firefox/.test(ver); if(isFF) document.addEventListener("DOMMouseScroll", handleScroll, false); else document.onmousewheel = handleScroll; function handleScroll(e) { e = e || event; var d = isFF? -e.detail: e.wheelDelta; ar += (d<0?-10:10); if(ar > 100) ar = 100; else if(ar < -100) ar = -100; if(isIE) { e.returnValue = false; } else { e.preventDefault(); e.stopPropagation(); } } function OnTimer() { var aX = dy / 100; var aY = -dx / 100; if(aX || aY) oCube.rotate(aX, aY); if(ar < 0) ar++, r--; else if(ar > 0) ar--, r++; else return; if(r < 80) r = 80; else if(r > 200) r = 200; oCube.setRadius(r); } function DoSearch(btn) { var word = btn.previousSibling.value; var id = btn.getAttribute("tid"); var url = MyFace[id].url.replace("%s", encodeURI(word)); window.open(url); } // ]]></script>
原文连接:Google Cube立方体
所有媒体,可在保留署名、
原文连接
的情况下转载,若非则不得使用我方内容。