CSS3D and WebGl playing together - Initial Experiments via a Cylindrical Family Tree

I got a few things straightened out with using both CSS3D and WebGl in a family tree viz. Lots still to do (especially on colors), but this seems pretty cool so far. Screenshots and some notes are below.

CSS3D Divs wrapped around a cylinder and mixing in webgl space with Bezier curves


A Div Merged with WebGL Space
The name is a hyperlink that works
Styling of the div is from basic css - scrollbar just to see if that worked (it does)

The latest efforts leaned heavily on:

The initial things worked out here had to do with getting html components to show up and be (mostly) placed properly in a 3D scene. This is done using the THREE.js CSS3DRenderer that mrdoob initially created back in 2012, coupled with Etienne's example. I also had to pull out the CSS3DRenderer.js and Projector.js from version 58 of three.js - I haven't gone back to see what the underlying problems were, but the latest wasn't working, and Etienne's (working) example used version 58.

The main idea is that for every little html element you want to use as a CSS3D object, you need to create a plane of the same size in the webgl space with opacity 0 and having blending function THREE.NoBlending:

    //create the div that will ultimately be put into 3D vis CSS3
    var element = document.createElement('div');
    //...details left out on adding the name and lifespan info

    var eInfo = {width:200, height:50, scaleX:0.25, scaleY: 0.25,z:1};

    element.style.width = eInfo.width + 'px';
    element.style.height = eInfo.height + 'px';
    element.style.opacity = 1;
    element.style.top = '0';
    element.className += ' css3d-name-div';
    //"node" contains info on the person;
    //   node color is based on gender
    element.style.border = '3px solid ' + node.getBasicColor();

    //create the CSS3D Object
    var objectCSS = new THREE.CSS3DObject( element );
    //place it where the original node was (//flip the y here)
    objectCSS.position.set(node.x,height-node.y,eInfo.z);  
    objectCSS.scale.set(eInfo.scaleX,eInfo.scaleY,1);

    //separate scene is used for the CSS3D objects
    sceneCSS.add(objectCSS);

    //create the webgl plane that has the same size, scaling, position, and 
    //  rotation of the corresponding CSS3D object
    var geometry = new THREE.PlaneGeometry(eInfo.width, eInfo.height);
    //material with special properties for this!
    var material = new THREE.MeshBasicMaterial({
                       blending: THREE.NoBlending, 
                       transparent: true,
                       opacity:0.0,
                       side: THREE.DoubleSide,
                       color: 0x000000} );
    var plane = new THREE.Mesh( geometry, material );

    plane.scale.copy(objectCSS.scale);
    plane.position.copy(objectCSS.position);
    // do this in general so that the plane is oriented the
    //    same as the CSS3DObject:
    plane.rotation.copy(objectCSS.rotation);

    //separate scene is used for the webgl objects
    scene.add(plane);
Main details in constructing a CSS3D object for a div
and the correspondig webgl plane object

I also confirmed that it's not hard to transition Bezier curves to the side of a cylinder - this was done as part of a test transition of the family tree to a cylinder, implemented based on how Steve Hall transitioned his d3 graphs to a helix shape.

Near-Term Remaining Things to Deal With
  • Fixed. This was due to a stray copy-paste margin-top of -2px.Proper placement of the "hidden" plane behind every CSS3D object that handles the magic of letting the CSS3D object blend in the scene - this means understanding what the "NoBlending" even does, and exactly how the size of the CSS3D rectangles is determined. There are some slight unwanted offsets in the current implementation.
  • More 3D cues - there are a number of things to look at here

Longer-term, it's unclear what the best way is - if any - to incorporate 3D into something like this. However, there are certainly lots of things to explore. And once the Oculus Rift is out early next year, it will be interesting to see what possibilities open up - for example, you could be in the middle of the cylindrical family tree. Cool stuff.

Popular Posts