3D实现思路分享
在CSS2中,我们的页面都是静态的,网页设计师也习惯把它作为页面效果的设计工具。但往往有些页面效果不只是静态的,比如说,如何实际移动一些元素?如何更改元素的外观——旋转或缩放? 多年来,Web设计师为了给修改页面的外观,都依赖于图片、Flash或JavaScript才能完成。不过,CSS3将要改变设计师这种思维,进入CSS3时代,借助CSS3就可以轻松倾斜、缩放、移动以及翻转元素。看以下两个例子之前先来了解CSS3的一些基本知识
'1: css3中-moz、-ms、-webkit分别代表的意思是什么呢? -moz代表firefox浏览器私有属性-ms代表ie浏览器私有属性-webkit代表safari、chrome -o'代表opera浏览器私有属性
2: px:绝对单位,页面按精确像素展示 em:相对单位,基准点为父节点字体的大小,如果自身定义了font-size按自身来计算(浏览器默认字体是16px),整个页面内1em不是一个固定的值。
3: box-sizing属性可以为三个值之一:content-box(default),border-box,padding-box。 content-box,border和padding不计算入width之内 padding-box,padding计算入width内 border-box,border和padding计算入width之内,其实就是怪异模式了~
4: perspective 属性定义 3D 元素距视图的距离,以像素计。该属性允许您改变 3D 元素查看 3D 元素的视图。 当为元素定义 perspective 属性时,其子元素会获得透视效果,而不是元素本身。 注释:perspective 属性只影响 3D 转换元素。
5: transform-style属性是3D空间一个重要属性,指定嵌套元素如何在3D空间中呈现。他主要有两个属性值:flat和preserve-3d。 其中flat值为默认值,表示所有子元素在2D平面呈现。preserve-3d表示所有子元素在3D空间中呈现。 也就是说,如果对一个元素设置了transform-style的值为flat,则该元素的所有子元素都将被平展到该元素的2D平面中进行呈现。沿着X轴或Y轴方向旋转该元素将导致位于正或负Z轴位置的子元素显示在该元素的平面上,而不是它的前面或者后面。如果对一个元素设置了transform-style的值为preserve-3d,它表示不执行平展操作,他的所有子元素位于3D空间中。
CSS3的transform属性指一组转换函数。 CSS3变形中具有X /Y可用的函数:'rotate()、translateY()、'translateX()、translateY()、scaleX()、scaleY()、skewX()和skewY()。
以下是一些例子
实例一
<!DOCTYPE html> <html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="UTF-8">
<title>HTML5 3D立方体旋转动画DEMO演示</title>
<link rel="stylesheet" href="css/style.css" media="screen" type="text/css">
</head>
<body>
<cube> <back></back> <bottom></bottom> <front></front> <left></left> <right></right> <top></top>
</cube> </body>
</html>
<style type="text/css"> * {
-webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;
}
html {
background: -webkit-radial-gradient(center, ellipse, #430d6d 0%, #000000 100%); background: radial-gradient(ellipse at center, #430d6d 0%, #000000 100%); height: 100%;
}
body {
width: 20em; height: 20em; left: 50%; margin-left: -10em; margin-top: -10em; -webkit-perspective: 1000px; -ms-perspective: 1000px; perspective: 1000px; position: absolute; top: 50%;
}
cube {
-webkit-animation: 6s spin linear infinite; animation: 6s spin linear infinite; height: 100%; position: absolute; -webkit-transform-style: preserve-3d; -ms-transform-style: preserve-3d; transform-style: preserve-3d; width: 100%;
}
cube * {
background: -webkit-linear-gradient(270deg, rgba(0, 0, 0, 0) 0px, rgba(54, 226, 248, 0.5) 0%, rgba(54, 226, 248, 0.5) 3px, rgba(0, 0, 0, 0) 0px), -webkit-linear-gradient(0deg, rgba(0, 0, 0, 0) 0px, rgba(54, 226, 248, 0.5) 0%, rgba(54, 226, 248, 0.5) 3px, rgba(0, 0, 0, 0) 0px); background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0px, rgba(54, 226, 248, 0.5) 0%, rgba(54, 226, 248, 0.5) 3px, rgba(0, 0, 0, 0) 0px), linear-gradient(90deg, rgba(0, 0, 0, 0) 0px, rgba(54, 226, 248, 0.5) 0%, rgba(54, 226, 248, 0.5) 3px, rgba(0, 0, 0, 0) 0px); -webkit-background-size: 2.5em 2.5em, 2.5em 2.5em; background-size: 2.5em 2.5em, 2.5em 2.5em; background-color: rgba(0, 0, 0, 0.5); border: 2px solid rgba(54, 226, 248, 0.5); -webkit-box-shadow: 0 0 5em rgba(0, 128, 0, 0.4); box-shadow: 0 0 5em rgba(0, 128, 0, 0.4); display: block; height: 20em; position: absolute; width: 20em;
}
cube *:before {
background: -webkit-radial-gradient(center, ellipse, rgba(0, 0, 0, 0) 30%, rgba(0, 128, 0, 0.2) 100%); background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0) 30%, rgba(0, 128, 0, 0.2) 100%); content: ; height: 100%; position: absolute; width: 100%;
}
back {
-webkit-transform: rotateX(180deg) translateZ(10em); -ms-transform: rotateX(180deg) translateZ(10em); transform: rotateX(180deg) translateZ(10em);
}
bottom {
-webkit-transform: rotateX(-90deg) translateZ(10em); -ms-transform: rotateX(-90deg) translateZ(10em); transform: rotateX(-90deg) translateZ(10em);
}
front {
-webkit-transform: rotateY(0deg) translateZ(10em); -ms-transform: rotateY(0deg) translateZ(10em); transform: rotateY(0deg) translateZ(10em);
}
left {
-webkit-transform: rotateY(-90deg) translateZ(10em); -ms-transform: rotateY(-90deg) translateZ(10em); transform: rotateY(-90deg) translateZ(10em);
}
right {
-webkit-transform: rotateY(90deg) translateZ(10em); -ms-transform: rotateY(90deg) translateZ(10em); transform: rotateY(90deg) translateZ(10em);
}
top {
-webkit-transform: rotateX(90deg) translateZ(10em); -ms-transform: rotateX(90deg) translateZ(10em); transform: rotateX(90deg) translateZ(10em);
}
@-webkit-keyframes spin {
from { -webkit-transform: translateZ(-10em) rotateX(0) rotateY(0deg); transform: translateZ(-10em) rotateX(0) rotateY(0deg); }
to { -webkit-transform: translateZ(-10em) rotateX(360deg) rotateY(360deg); transform: translateZ(-10em) rotateX(360deg) rotateY(360deg); }
}
@keyframes spin {
from { -webkit-transform: translateZ(-10em) rotateX(0) rotateY(0deg); transform: translateZ(-10em) rotateX(0) rotateY(0deg); }
to { -webkit-transform: translateZ(-10em) rotateX(360deg) rotateY(360deg); transform: translateZ(-10em) rotateX(360deg) rotateY(360deg); }
}
</style>
实例二
<!DOCTYPE html> <html>
<head>
<meta charset="UTF-8">
<title>HTML5 SVG 3D空间模型DEMO演示</title>
<link rel="stylesheet" href="css/style.css" media="screen" type="text/css" />
</head>
<body>
<main> <article> <section id="perspective"> <svg id="grid"> <rect x="1" y="1" width="998" height="998"/> <line x1="200" y1="2" x2="200" y2="998"/> <line x1="400" y1="2" x2="400" y2="998"/> <line x1="600" y1="2" x2="600" y2="998"/> <line x1="800" y1="2" x2="800" y2="998"/> <line x1="2" y1="200" x2="998" y2="200"/> <line x1="2" y1="400" x2="998" y2="400"/> <line x1="2" y1="600" x2="998" y2="600"/> <line x1="2" y1="800" x2="998" y2="800"/> </svg> <section id="axis"> <figure id="X">
</figure> <figure id="Y">
</figure> <figure id="Z">
</figure> </section> <section id="graph"></section> </section> </article> <nav> <button onmousedown="select(this)">Pan</button> <button onmousedown="select(this)">Rotate</button> <button onmousedown="select(this)">Zoom</button> <button onmousedown="resetViewport()">Reset viewport</button> <section id="menu">Your menu</section> </nav> <label>‹</label> <aside>
This CSS 3D project works fine only in WebKit based browsers
Middle mouse button - Pan view
Alt + Left mouse button - Rotate view
Scroll wheel - Zoom in / out
</aside>
</main>
<script type="text/javascript"> var $ = document.querySelectorAll.bind(document);
/* -------------------------------- */ /* ---------- Navigation ---------- */ /* -------------------------------- */ var article = $('article')[0]; var perspective = $('#perspective')[0]; var buttons = $('button');
var click = false; var cursor = { x: 0, y: 0 }; var transform = { position: { x: 0, y: 0 }, rotation: { x: 0, y: 0 }, zoom: 0 }; var target = { position: { x: 0, y: 0 }, rotation: { x: -20, y: -45 }, zoom: 100 }; var targetOnDown = { position: { x: 0, y: 0 }, rotation: { x: 0, y: 0 }, zoom: 0 };
article.onmousedown = function(e) { if (e.which < 3) { if (e.which == 2) article.className = 'pan'; if (article.className == 'pan') article.style.cursor = '-webkit-grabbing'; cursor.x = e.pageX; cursor.y = e.pageY; targetOnDown.position.x = target.position.x; targetOnDown.position.y = target.position.y; targetOnDown.rotation.x = target.rotation.x; targetOnDown.rotation.y = target.rotation.y; targetOnDown.zoom = target.zoom; click = true; } }; article.onmousemove = function(e) { if (click) { switch (article.className) { case 'pan': target.position.x = targetOnDown.position.x + e.pageX - cursor.x; target.position.y = targetOnDown.position.y + e.pageY - cursor.y; break;
case 'rotate': target.rotation.x = targetOnDown.rotation.x - (e.pageY - cursor.y) * 0.3; target.rotation.y = targetOnDown.rotation.y + (e.pageX - cursor.x) * 0.3; break;
case 'zoom': target.zoom = targetOnDown.zoom - (e.pageY - cursor.y) * 0.4; if (target.zoom < 50) target.zoom = 50; break; } } }; article.onmouseup = function(e) { click = false; if (article.className == 'pan') article.style.cursor = ; if (e.which == 2) returnValue(); };
onkeydown = function(e) { if (e.altKey) article.className = 'rotate'; }; onkeyup = function(e) { if (e.keyCode == 18) returnValue(); };
article.addEventListener('mousewheel', scroll, false); article.addEventListener('DOMMouseScroll', scroll, false); function scroll(e) { e.preventDefault(); var delta = (e.wheelDelta) ? e.wheelDelta : - e.detail; target.zoom += (delta > 0) ? 15 : -15; if (target.zoom < 50) target.zoom = 50; }
function select(button) { [].forEach.call(buttons, function(b) { if (b != button) b.removeAttribute('class'); }); (button.className) ? button.removeAttribute('class') : button.className = 'selected'; switch (button.innerHTML) { case 'Pan': (article.className == 'pan') ? article.removeAttribute('class') : article.className = 'pan'; break; case 'Rotate': (article.className == 'rotate') ? article.removeAttribute('class') : article.className = 'rotate'; break; case 'Zoom': (article.className == 'zoom') ? article.removeAttribute('class') : article.className = 'zoom'; break; } }
function returnValue() { for (var i = 0; i < buttons.length; i++) if (buttons[i].className == 'selected') var str = buttons[i].innerHTML.toLowerCase(); if (str) article.className = str; else article.removeAttribute('class'); }
function resetViewport() { target.position.x = target.position.y = 0; target.rotation.x = -20; target.rotation.y = -45; target.zoom = 100; }
(function animate() { transform.position.x += (target.position.x - transform.position.x) * 0.2; transform.position.y += (target.position.y - transform.position.y) * 0.2; transform.rotation.x += (target.rotation.x - transform.rotation.x) * 0.1; transform.rotation.y += (target.rotation.y - transform.rotation.y) * 0.1; transform.zoom += (target.zoom - transform.zoom) * 0.1;
transform.position.x = parseFloat(transform.position.x.toFixed(2)); transform.position.y = parseFloat(transform.position.y.toFixed(2)); transform.rotation.x = parseFloat(transform.rotation.x.toFixed(2)); transform.rotation.y = parseFloat(transform.rotation.y.toFixed(2)); transform.zoom = parseFloat(transform.zoom.toFixed(2));
perspective.style.transform = perspective.style.msTransform = perspective.style.mozTransform = perspective.style.webkitTransform = 'translate(' + transform.position.x + 'px, ' + transform.position.y + 'px) rotateX(' + transform.rotation.x + 'deg) rotateY(' + transform.rotation.y + 'deg) scale3d(' + transform.zoom / 100 + ', ' + transform.zoom / 100 + ', ' + transform.zoom / 100 + ')'; requestAnimationFrame(animate); })();
</script>
</body>
</html>
以下是一些参考资料
linear-gradient讲解
http://www.cnblogs.com/lhb25/archive/2013/01/30/css3-linear-gradient.html
transform 讲解
http://www.w3cplus.com/content/css3-transform/
http://www.alixixi.com/web/a/2013112291742.shtml
perspective讲解
http://blog.163.com/hongshaoguoguo@126/blog/static/18046981201392411302262/
animation讲解