ThreeJS实现波纹粒⼦效果
今天我们来⽤ThreeJS的库实现⼀个波纹粒⼦效果,我们⽤到的ThreeJS的库有CanvasRenderer.js,OrbitControls.js,Projector.js,stats.min.js和three.js。这些库都是不可或缺的,我们先来看看实现的效果,如下图所⽰。
我们再来看看项⽬结构是怎么样的,项⽬结构如下图所⽰。
我们的效果全部写在了index.html⾥,现在我们直接贴出index.html的代码,同学们可以直接拿来运⾏,代码如下。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>演⽰页⾯</title>
<script src="three.js"></script>
<script src="Projector.js"></script>
<script src="CanvasRenderer.js"></script>
<script src="stats.min.js"></script>
<script src="OrbitControls.js"></script>
</head>
<body>
</body>
<script>
var SEPARATION = 200,
AMOUNTX = 60,
AMOUNTY = 60;
var container, stats;
var camera, scene, renderer, controls;
var particles, particle, count = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function init() {
container = ateElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
scene = new THREE.Scene();
/**
* 设置光源
* */
//点光源
var point = new THREE.PointLight(0xffffff);//⽩光
point.position.set(1200, 1200, 1200);//点光源位置
scene.add(point);//点光源添加进场景
//环境光
var ambient = new THREE.AmbientLight(0x999999);//⽩光
scene.add(ambient);//环境光添加进场景
//模型
var cubeGeometry = new THREE.CubeGeometry(1000, 1000, 1000);
var cubeMaterial = new THREE.MeshLambertMaterial({
color:0xffff00
//side:THREE.DoubleSide
});//材质对象
var cubeMesh = new THREE.Mesh(cubeGeometry, cubeMaterial);//⽹格模型对象
scene.add(cubeMesh);//正⽅体⽹格模型添加到场景中
/
/粒⼦
particles = new Array();
var PI2 = Math.PI * 2;
var material = new THREE.SpriteCanvasMaterial({
color: 0xffffff,
program: function(context) {
context.beginPath();
context.arc(0, 0, 0.5, 0, PI2, true);
context.fill();
}
});
var i = 0;
for (var ix = 0; ix < AMOUNTX; ix++) {
for (var iy = 0; iy < AMOUNTY; iy++) {
particle = particles[i++] = new THREE.Sprite(material);
particle.position.x = ix * SEPARATION - ((AMOUNTX * SEPARATION) / 2); particle.position.z = iy * SEPARATION - ((AMOUNTY * SEPARATION) / 2); scene.add(particle);
}
}
/**
* 创建渲染器对象
* */
renderer = new THREE.CanvasRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
window.addEventListener('resize', onWindowResize, false);
//交互控制器
/**
* ⿏标键盘事件
* */
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.dampingFactor = 0.1;
controls.screenSpacePanning = true;
controls.minDistance = 0;
controls.maxDistance = 5000;
controls.maxPolarAngle = 2*Math.PI;
/**
* 模型拾取
* */
mouse.x = -10000;
mouse.y = -10000;
function onMouseMove( event ) {
/
/ calculate mouse position in normalized device coordinates
// (-1 to +1) for both components
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
window.addEventListener( 'mousemove', onMouseMove, false );
}
function pickUp() {
// update the picking ray with the camera and mouse position
raycaster.setFromCamera( mouse, camera );
// calculate objects intersecting the picking ray
var intersects = raycaster.intersectObjects( scene.children );
for ( var i = 0; i < intersects.length; i++ ) {
intersects[ i ].lor.set( 0xff00ff );
}
if(intersects.length === 0){
scene.children[2].lor.set( 0xffff00 );
for(var i=3; i<scene.children.length; i++){
scene.children[i].lor.set( 0xffffff );
}
}
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
var rad = 0;
function render() {
camera.position.set(2600, 500, 2600);
camera.up = new THREE.Vector3(0, 1, 0);
camera.lookAt(new THREE.Vector3(0, 500, 0));
var i = 0;
for (var ix = 0; ix < AMOUNTX; ix++) {
for (var iy = 0; iy < AMOUNTY; iy++) {
particle = particles[i++];
particle.position.y = (Math.sin((ix + count) * 0.2) * 500) +
(Math.sin((iy + count) * 0.2) * 500);
particle.scale.y = (Math.sin((ix + count) * 0.3) + 1) * 3 +
(Math.sin((iy + count) * 0.3) + 1) * 3;
particle.scale.x = (Math.sin((ix + count) * 0.3) + 1) * 3 +
(Math.sin((iy + count) * 0.3) + 1) * 3;
}
scene.children[2].s(ix + count/2)*5);
}
//模型旋转
scene.children[2].rotateY(Math.PI/180);
camera.position.x = s(Math.PI/180*rad);
camera.position.z = -2600*Math.sin(Math.PI/180*rad);
//点光源位置
scene.children[0].position.x = s(Math.PI/180*rad+Math.PI*0.1);
scene.children[0].position.z = -1200*Math.sin(Math.PI/180*rad+Math.PI*0.1);
controls.update();
count += 0.1;
rad += 0.2;
}
function animate() {
requestAnimationFrame(animate);
render();
pickUp();
}实现特效的代码js
init();
animate();
</script>
</html>
我们分析⼀下段代码,⾸先我们看到requestAnimationFrame,这是主循环,我们在init()初始化函数中往scene场景中添加了particle粒⼦,这些粒⼦是在XoZ平⾯上均匀⽹格散布的。然后我们主循环每次render()都改变粒⼦的Y坐标,修改的规则是通过sin函数进⾏Y轴向扰动。每次重绘我们都修改Y坐标,就实现了粒⼦的波动特效。
代码很简单,希望能帮助⼤家做出⼀套粒⼦波动的背景特效。鲫鱼⾮常愿意和⼤家讨论学习WebGL和ThreeJS的技术,欢迎⼤家留⾔,谢谢。本⽂系原创,如需引⽤请注明出处:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论