Skip to content

Instantly share code, notes, and snippets.

@sepans
Last active September 11, 2015 14:23
Show Gist options
  • Save sepans/f0cb08a52269a6a3e8ab to your computer and use it in GitHub Desktop.
Save sepans/f0cb08a52269a6a3e8ab to your computer and use it in GitHub Desktop.
particles
<div id="container"></div>
<div id='sections'>
<section class="step active">
<div class="title">Title</div>
data not too large and managable
</section>
<section class="step">
<div class="title">Title 2</div>
your data grows as your business grows
</section>
<section class="step">
<div class="title">Title 3</div>
Examine data more closely
</section>
<section class="step">
<div class="title">Title 4</div>
discover relations in your data
</section>
<section class="step">
<div class="title">Title 5</div>
Get the big picture
</section>
</div>
var group;
var container, stats;
var particlesData = [];
var camera, scene, renderer;
var positions, colors;
var pointCloud;
var particlePositions;
var linesMesh;
var maxParticleCount = 1000;
var particleCount = 300;
var r = 800;
var rHalf = r / 2;
var effectController = {
showDots: true,
showLines: true,
minDistance: 10,
limitConnections: false,
maxConnections: 20,
particleCount: 300
}
init();
animate();
function initGUI() {
var gui = new dat.GUI();
gui.add(effectController, "showDots").onChange(function(value) {
pointCloud.visible = value;
});
gui.add(effectController, "showLines").onChange(function(value) {
linesMesh.visible = value;
});
gui.add(effectController, "minDistance", 10, 300);
gui.add(effectController, "limitConnections");
gui.add(effectController, "maxConnections", 0, 30, 1);
gui.add(effectController, "particleCount", 0, maxParticleCount, 1).onChange(function(value) {
particleCount = parseInt(value);
particles.drawcalls[0].count = particleCount;
});
}
/*
setTimeout(function() {
addDots();
}, 2500);
setTimeout(function() {
zoom(1200);
}, 4000);
setTimeout(function() {
zoom(1750);
}, 10000);
setTimeout(animateConnections, 12000);
*/
var scrollFunctions = [ addDots, function() {zoom(800)}, animateConnections, function() {zoom(1750)}];
var scrollFunctionsCalled = [false, false, false, false];
function initScroll() {
var sectionPositions = [];
var sections = document.querySelectorAll('.step');//$('.step');
var startPos;
[].forEach.call(sections,function(d,i) {
var top = d.getBoundingClientRect().top;
if(i === 0) {
startPos = top;
}
sectionPositions.push(top - startPos);
});
var $document = $(this);
// thia ia nor good! refactor!
$document.scroll(function() {
for (var i = sectionPositions.length-1; i >= 0 ; i--) {
if ($document.scrollTop() >= sectionPositions[i] + 700) {
// console.log(' section' + i, scrollFunctionsCalled[i] );
if(!scrollFunctionsCalled[i]) {
//$(sections).removeClass('active');
//$(sections[i+1]).addClass('active');
sections[i].classList.remove('active');
sections[i+1].classList.add('active');
console.log(i+1,sections[i+1], sections[i+1].classList);
//sections[]
scrollFunctions[i]();
scrollFunctionsCalled[i] = true;
}
break;
}
}
})
}
function init() {
//initGUI();
initScroll();
container = document.getElementById('container');
//
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 4000);
camera.position.z = 1750;
controls = new THREE.OrbitControls(camera, container);
scene = new THREE.Scene();
group = new THREE.Group();
scene.add(group);
/*
var helper = new THREE.BoxHelper( new THREE.Mesh( new THREE.BoxGeometry( r, r, r ) ) );
helper.material.color.setHex( 0x030303 );
helper.material.blending = THREE.AdditiveBlending;
helper.material.transparent = true;
group.add( helper );
*/
var segments = maxParticleCount * maxParticleCount;
positions = new Float32Array(segments * 3);
colors = new Float32Array(segments * 3);
var pMaterial = new THREE.PointCloudMaterial({
color: 0xC5C5FF,
size: 3,
blending: THREE.AdditiveBlending,
transparent: true,
sizeAttenuation: false
});
particles = new THREE.BufferGeometry();
particlePositions = new Float32Array(maxParticleCount * 3);
for (var i = 0; i < maxParticleCount; i++) {
var x = Math.random() * r - r / 2;
var y = Math.random() * r - r / 2;
var z = Math.random() * r - r / 2;
particlePositions[i * 3] = x;
particlePositions[i * 3 + 1] = y;
particlePositions[i * 3 + 2] = z;
// add it to the geometry
particlesData.push({
velocity: new THREE.Vector3(0, 0, 0),
//velocity: new THREE.Vector3( -1 + Math.random() * 2, -1 + Math.random() * 2, -1 + Math.random() * 2 ),
numConnections: 0
});
}
particles.drawcalls.push({
start: 0,
count: particleCount,
index: 0
});
particles.addAttribute('position', new THREE.DynamicBufferAttribute(particlePositions, 3));
// create the particle system
pointCloud = new THREE.PointCloud(particles, pMaterial);
group.add(pointCloud);
var geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.DynamicBufferAttribute(positions, 3));
geometry.addAttribute('color', new THREE.DynamicBufferAttribute(colors, 3));
geometry.computeBoundingSphere();
geometry.drawcalls.push({
start: 0,
count: 0,
index: 0
});
var material = new THREE.LineBasicMaterial({
vertexColors: 0xFF0000, //THREE.VertexColors,
blending: THREE.AdditiveBlending,
transparent: true
});
linesMesh = new THREE.Line(geometry, material, THREE.LinePieces);
group.add(linesMesh);
//
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.gammaInput = true;
renderer.gammaOutput = true;
container.appendChild(renderer.domElement);
//
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild(stats.domElement);
window.addEventListener('resize', onWindowResize, false);
/*
setTimeout(function() {
addDots();
}, 2500);
setTimeout(function() {
zoom(1200);
}, 4000);
setTimeout(function() {
zoom(1750);
}, 10000);
setTimeout(animateConnections, 12000);
*/
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
var vertexpos = 0;
var colorpos = 0;
var numConnected = 0;
for (var i = 0; i < particleCount; i++)
particlesData[i].numConnections = 0;
for (var i = 0; i < particleCount; i++) {
// get the particle
var particleData = particlesData[i];
particlePositions[i * 3] += particleData.velocity.x;
particlePositions[i * 3 + 1] += particleData.velocity.y;
particlePositions[i * 3 + 2] += particleData.velocity.z;
if (particlePositions[i * 3 + 1] < -rHalf || particlePositions[i * 3 + 1] > rHalf)
particleData.velocity.y = -particleData.velocity.y;
if (particlePositions[i * 3] < -rHalf || particlePositions[i * 3] > rHalf)
particleData.velocity.x = -particleData.velocity.x;
if (particlePositions[i * 3 + 2] < -rHalf || particlePositions[i * 3 + 2] > rHalf)
particleData.velocity.z = -particleData.velocity.z;
if (effectController.limitConnections && particleData.numConnections >= effectController.maxConnections)
continue;
// Check collision
for (var j = i + 1; j < particleCount; j++) {
var particleDataB = particlesData[j];
if (effectController.limitConnections && particleDataB.numConnections >= effectController.maxConnections)
continue;
var dx = particlePositions[i * 3] - particlePositions[j * 3];
var dy = particlePositions[i * 3 + 1] - particlePositions[j * 3 + 1];
var dz = particlePositions[i * 3 + 2] - particlePositions[j * 3 + 2];
var dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (dist < effectController.minDistance) {
particleData.numConnections++;
particleDataB.numConnections++;
var alpha = 1.0 - dist / effectController.minDistance;
positions[vertexpos++] = particlePositions[i * 3];
positions[vertexpos++] = particlePositions[i * 3 + 1];
positions[vertexpos++] = particlePositions[i * 3 + 2];
positions[vertexpos++] = particlePositions[j * 3];
positions[vertexpos++] = particlePositions[j * 3 + 1];
positions[vertexpos++] = particlePositions[j * 3 + 2];
colors[colorpos++] = alpha;
colors[colorpos++] = alpha;
colors[colorpos++] = alpha;
colors[colorpos++] = alpha;
colors[colorpos++] = alpha;
colors[colorpos++] = alpha;
numConnected++;
}
}
}
linesMesh.visible = effectController.showLines;
linesMesh.geometry.drawcalls[0].count = numConnected * 2;
linesMesh.geometry.attributes.position.needsUpdate = true;
linesMesh.geometry.attributes.color.needsUpdate = true;
pointCloud.geometry.attributes.position.needsUpdate = true;
requestAnimationFrame(animate);
stats.update();
render();
}
//var i = 0;
function render() {
var time = Date.now() * 0.001;
group.rotation.y = time * 0.02;
renderer.render(scene, camera);
}
function addDots() {
var tween = new createjs.Tween(particles.drawcalls[0]).to({
count: 800
}, 4000, createjs.Ease.getPowInOut(4));
}
function animateConnections() {
var minDistTween = new createjs.Tween(effectController).to({
minDistance: r / 6
}, 8000, createjs.Ease.getPowInOut(4));
}
function zoom(zoomTo) {
var zTween = new createjs.Tween(camera.position).to({
z: zoomTo ? zoomTo : 1200
}, 5000, createjs.Ease.getPowInOut(4));
}
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="http://threejs.org/examples/js/libs/dat.gui.min.js"></script>
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="http://threejs.org/examples/js/libs/stats.min.js"></script>
<script src="https://code.createjs.com/tweenjs-0.6.1.min.js"></script>
body {
color: #cccccc;
font-family: Monospace;
font-size: 13px;
text-align: center;
background-color: #000000;
margin: 0px;
/*overflow: hidden;*/
height: 100%;
}
body {
height: 100%;
}
#container {
position: fixed;
top: 50px;
pointer-events:none;
}
#sections {
width: 100%;
overflow-y: scroll;
height: 100%;
margin-top: 150px;
}
section {
height: 850px;
overflow-y: hide;
opacity: 0.1;
font-size: 16px;
transition: opacity 1s ease-in;
margin-top: 100px;
}
section.active {
opacity: 0.9;
}
.step .title {
font-size: 24px;
}
a {
color: #0080ff;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment