手把手教你做一个CSS 3D云
介绍:之前在runjs分享了个3d云,今天在这分享个制作过程。这是个简化版,为了减轻浏览器打开时的压力去掉了云流动效果和鼠标滚轴效果。
1.创建一个模型和相机
首先,定义两个div:viewport和world。其他剩余元素动态创建。viewport全屏铺开,用它作为相机的一个平面。这里的相机你可以认为是真实世界里一块薄玻璃。我们可以移动玻璃的位置,来使我们看到不同的视角。world元素用来放置我们的一些css 3d效果。代码如下:
<div id="viewport">
<div id="world"></div>
</div>
接下来对css属性进行定义:
#viewport {
-webkit-perspective: 400;
-moz-perspective: 400;
-o-perspective: 400;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
overflow: hidden;
background-image: linear-gradient(bottom, rgb(69,132,180) 28%, rgb(31,71,120) 64%);
background-image: -o-linear-gradient(bottom, rgb(69,132,180) 28%, rgb(31,71,120) 64%);
background-image: -moz-linear-gradient(bottom, rgb(69,132,180) 28%, rgb(31,71,120) 64%);
background-image: -webkit-linear-gradient(bottom, rgb(69,132,180) 28%, rgb(31,71,120) 64%);
background-image: -ms-linear-gradient(bottom, rgb(69,132,180) 28%, rgb(31,71,120) 64%);
background-image: -webkit-gradient(
linear,
left bottom,
left top,
color-stop(0.28, rgb(69,132,180)),
color-stop(0.64, rgb(31,71,120))
);
}
#world {
position: absolute;
left: 50%;
top: 50%;
margin-left: -256px;
margin-top: -256px;
height: 512px;
width: 512px;
background-color: rgba( 255, 0, 0, .2 );
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
}
viewport的属性定义主要是模仿天空的效果,world模仿一个块状元素
添加鼠标移动效果:
/*
定义变量
worldXAngle,worldYAngle表示world的x轴,y轴旋转偏移
d代表着景深
*/
var world = document.getElementById( 'world' ),
viewport = document.getElementById( 'viewport' ),
worldXAngle = 0,
worldYAngle = 0,
d = 0;
/*
鼠标移动位置的事件监听器
从-180到180,包括垂直和水平
*/
window.addEventListener( 'mousemove', function( e ) {
worldYAngle = -( .5 - ( e.clientX / window.innerWidth ) ) * 180;
worldXAngle = ( .5 - ( e.clientY / window.innerHeight ) ) * 180;
updateView();
} );
/*
修改world的变换属性
通过d像素改变world x,y,z轴各个属性值
*/
function updateView() {
var t = 'translateZ( ' + d + 'px ) rotateX( ' + worldXAngle + 'deg) rotateY( ' + worldYAngle + 'deg)';
world.style.webkitTransform = t;
world.style.MozTransform = t;
world.style.oTransform = t;
}
2.向模型中添加对象
现在开始向world模型中添加真正的3D内容了,在world的相对空间内添加一些细碎的div。div的属性如下:
.cloudBase {
background-color: rgba( 255, 0, 255, .5 );
position: absolute;
left: 256px;
top: 256px;
width: 20px;
height: 20px;
margin-left: -10px;
margin-top: -10px;
}
接下来我们使用generate()和
createCloud()来填充world元素,如下在js中添加下面两个方法:
/*
清理前一次渲染的div并且生成新的div
*/
function generate() {
objects = [];
if ( world.hasChildNodes() ) {
while ( world.childNodes.length >= 1 ) {
world.removeChild( world.firstChild );
}
}
for( var j = 0; j < 5; j++ ) {
objects.push( createCloud() );
}
}
/*
生成“云朵”div,随机分布,区间在-256到256之间
*/
function createCloud() {
var div = document.createElement( 'div' );
div.className = 'cloudBase';
var x = 256 - ( Math.random() * 512 );
var y = 256 - ( Math.random() * 512 );
var z = 256 - ( Math.random() * 512 );
var t = 'translateX( ' + x + 'px ) translateY( ' + y + 'px ) translateZ( ' + z + 'px )';
div.style.webkitTransform = t;
div.style.MozTransform = t;
div.style.oTransform = t;
world.appendChild( div );
return div;
}
3.为对象创建层
接下来我们为每一个cloudBase div添加一个绝对定位的.cloudLayer层div。.cloudLayer属性如下:
.cloudLayer {
position: absolute;
left: 50%;
top: 50%;
width: 256px;
height: 256px;
margin-left: -128px;
margin-top: -128px;
background-color: rgba( 0, 255, 255, .1 );
-webkit-transition: opacity .5s ease-out;
-moz-transition: opacity .5s ease-out;
-o-transition: opacity .5s ease-out;
}
oh,这个地方还要重新改一下createCloud()方法,让他也能随机生成几个“云层”。
/*
生成“云朵”div,随机分布,区间在-256到256之间
*/
function createCloud() {
var div = document.createElement( 'div' );
div.className = 'cloudBase';
var x = 256 - ( Math.random() * 512 );
var y = 256 - ( Math.random() * 512 );
var z = 256 - ( Math.random() * 512 );
var t = 'translateX( ' + x + 'px ) translateY( ' + y + 'px ) translateZ( ' + z + 'px )';
div.style.webkitTransform = t;
div.style.MozTransform = t;
div.style.oTransform = t;
world.appendChild( div );
for( var j = 0; j < 5 + Math.round( Math.random() * 10 ); j++ ) {
var cloud = document.createElement( 'div' );
cloud.className = 'cloudLayer';
var x = 256 - ( Math.random() * 512 );
var y = 256 - ( Math.random() * 512 );
var z = 100 - ( Math.random() * 200 );
var a = Math.random() * 360;
var s = .25 + Math.random();
x *= .2; y *= .2;
cloud.data = {
x: x,
y: y,
z: z,
a: a,
s: s
};
var t = 'translateX( ' + x + 'px ) translateY( ' + y + 'px ) translateZ( ' + z + 'px ) rotateZ( ' + a + 'deg ) scale( ' + s + ' )';
cloud.style.webkitTransform = t;
cloud.style.MozTransform = t;
cloud.style.oTransform = t;
div.appendChild( cloud );
layers.push( cloud );
}
return div;
}
现在你应该能看到成片的“云朵”了,虽然他们还是规则的几何形状,no hashion!不要急,接下来我们给他们点立体效果看看。
4.制作3D效果
魔术即将上演,定义个layer[]数据把所有world中的layer放到这个数组中,然后在新添加在update方法中遍历数组,动态的给world中元素的位置赋值。update()方法如下:
function update (){
for( var j = 0; j < layers.length; j++ ) {
var layer = layers[ j ];
layer.data.a += layer.data.speed;
var t = 'translateX( ' + layer.data.x + 'px ) translateY( ' + layer.data.y + 'px ) translateZ( ' + layer.data.z + 'px ) rotateY( ' + ( - worldYAngle ) + 'deg ) rotateX( ' + ( - worldXAngle ) + 'deg ) scale( ' + layer.data.s + ')';
layer.style.webkitTransform = t;
layer.style.MozTransform = t;
layer.style.oTransform = t;
}
requestAnimationFrame( update );
}
现在看起来有了3D效果,但是还是一堆图形,no hashion!丑小鸭如何变白天鹅呢?
5.终结者
最后一步很简单啦,把layer中的backgroud-image替换成一张云的图片就行啦(当然你也可以换成其他图片,比如暴风,血浆,甚至*),最好是png透明格式的。只需改下createCloud。
/*
生成“云朵”div,随机分布,区间在-256到256之间
*/
function createCloud() {
var div = document.createElement( 'div' );
div.className = 'cloudBase';
var x = 256 - ( Math.random() * 512 );
var y = 256 - ( Math.random() * 512 );
var z = 256 - ( Math.random() * 512 );
var t = 'translateX( ' + x + 'px ) translateY( ' + y + 'px ) translateZ( ' + z + 'px )';
div.style.webkitTransform = t;
div.style.MozTransform = t;
div.style.oTransform = t;
world.appendChild( div );
for( var j = 0; j < 5 + Math.round( Math.random() * 10 ); j++ ) {
var cloud = document.createElement( 'img' );
cloud.style.opacity = 0;
var r = Math.random();
var src = 'cloud.png';
( function( img ) { img.addEventListener( 'load', function() {
img.style.opacity = .8;
} ) } )( cloud );
cloud.setAttribute( 'src', src );
cloud.className = 'cloudLayer';
var x = 256 - ( Math.random() * 512 );
var y = 256 - ( Math.random() * 512 );
var z = 100 - ( Math.random() * 200 );
var a = Math.random() * 360;
var s = .25 + Math.random();
x *= .2; y *= .2;
cloud.data = {
x: x,
y: y,
z: z,
a: a,
s: s,
speed: .1 * Math.random()
};
var t = 'translateX( ' + x + 'px ) translateY( ' + y + 'px ) translateZ( ' + z + 'px ) rotateZ( ' + a + 'deg ) scale( ' + s + ' )';
cloud.style.webkitTransform = t;
cloud.style.MozTransform = t;
cloud.style.oTransform = t;
div.appendChild( cloud );
layers.push( cloud );
}
return div;
}
c哈看下效果,一朵朵云像棉花糖一样盛开了!
不够完美,还带有边框,没关系接下来我们把这些边框去掉。
.cloudLayer {
background-color: rgba( 0, 255, 255, .1 );
}
#world {
background-color: rgba( 255, 0, 0, .2 );
}
.cloudBase {
background-color: rgba( 255, 0, 255, .5 );
}
把这三个背景去掉,ok啦!
效果演示地址:http://runjs.cn/detail/wudd1hfo
http://runjs.cn/detail/cgsofbsg 爆炸效果
转载于:https://my.oschina.net/mousai/blog/131796
上一篇: CSS3:3D转换