Skip to content

Instantly share code, notes, and snippets.

@artzub
Last active August 2, 2016 20:21
Show Gist options
  • Save artzub/4714063 to your computer and use it in GitHub Desktop.
Save artzub/4714063 to your computer and use it in GitHub Desktop.
Three.js and D3 Force layout (d3.behavior.zoom)
<!DOCTYPE html>
<html>
<head>
<title>Three ans D3</title>
<style>
body, html {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
position: relative;
overflow: hidden;
background: #111;
}
</style>
<script src="https://rawgithub.com/mrdoob/three.js/r55/build/three.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<script>
var container, stats, valid;
var camera, scene, renderer, group, particle;
var mouseX = 0, mouseY = 0;
var force, nodes = [], links = [];
var part = new Image();
part.src = "particle.png";
part.onload = function() {
init();
animate();
};
var w2 = document.body.clientWidth / 2;
var h2 = document.body.clientHeight / 2;
function colorize(img, r, g, b, a) {
if (!img)
return img;
var tempFileCanvas = document.createElement("canvas");
tempFileCanvas.width = img.width;
tempFileCanvas.height = img.height;
var imgCtx = tempFileCanvas.getContext("2d"), imgdata, i;
imgCtx.clearRect(0, 0, img.width, img.height);
imgCtx.save();
imgCtx.drawImage(img, 0, 0);
imgdata = imgCtx.getImageData(0, 0, img.width, img.height);
i = imgdata.data.length;
while((i -= 4) > -1) {
imgdata.data[i + 3] = imgdata.data[i] * a;
if (imgdata.data[i + 3]) {
imgdata.data[i] = r;
imgdata.data[i + 1] = g;
imgdata.data[i + 2] = b;
}
}
imgCtx.putImageData(imgdata, 0, 0);
imgCtx.restore();
return tempFileCanvas;
}
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera(h2 * 2, w2 / h2, 99, 101);
camera.position.z = 100;
scene = new THREE.Scene();
var group = new THREE.Object3D();
var PI2 = Math.PI * 2;
var program = function ( ctx, color ) {
color = d3.rgb(ctx.fillStyle);
ctx.drawImage(part, 0.5, 0.5, 1, 1);
};
var lineMaterial = new THREE.LineBasicMaterial({
color: 0xff0000,
opacity:.1
});
var particleMaterial = new THREE.ParticleBasicMaterial({
size: 0.1,
blending: THREE.AdditiveBlending, // required
depthTest: false, // required
transparent: true,
opacity: 0.7,
vertexColors: true // optional
});
/*new THREE.ParticleCanvasMaterial( {
color: Math.random() * 0x808008 + 0x808080,
program: program
} )*/
for ( var i = 0,j; i < 500; i++ ) {
var pm = particleMaterial.clone();
pm.color = new THREE.Color();
pm.color.setHSV(Math.random(), 1, 1);
var c = d3.rgb(pm.color.getStyle());
pm.map = new THREE.Texture( colorize(part, c.r, c.g, c.b, 1) );
particle = new THREE.Particle(pm);
particle.position.x = (Math.random() * w2 * 4 - w2 * 2);
particle.position.y = (Math.random() * h2 * 4 - h2 * 2);
particle.position.z = 0;
particle.scale.x = particle.scale.y = Math.random();
j = nodes.push(particle.position);
j = links.push({source : j % 10, target : j - 1});
j = links[j - 1];
stats = new THREE.Geometry();
stats.vertices.push(new THREE.Vertex(nodes[j.source]));
stats.vertices.push(new THREE.Vertex(nodes[j.target]));
group.add(new THREE.Line(stats, lineMaterial));
group.add( particle );
}
scene.add(group);
renderer = new THREE.CanvasRenderer();
renderer.setSize( w2 * 2, h2 * 2 );
container.appendChild( renderer.domElement );
d3.select(renderer.domElement)
.call(d3.behavior.zoom()
.scaleExtent([0.01, 8])
.scale(1)
.translate([group.position.x, group.position.y])
.on("zoom", function() {
group.scale.z = d3.event.scale;
//camera.position.z = d3.event.scale;
group.position.x = d3.event.translate[0];
group.position.y = d3.event.translate[1];
valid = false;
}));
window.addEventListener( 'resize', onWindowResize, false );
force = d3.layout.force()
.nodes(nodes)
.links(links)
.on("tick", function() {
valid = false;
})
.start();
}
function onWindowResize() {
w2 = window.innerWidth / 2;
h2 = window.innerHeight / 2;
camera.aspect = w2/h2;
camera.updateProjectionMatrix();
renderer.setSize( w2 * 2, h2 * 2 );
valid = false;
}
function animate() {
requestAnimationFrame( animate );
if (!valid) {
valid = true;
render();
}
}
function render() {
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment