-
Notifications
You must be signed in to change notification settings - Fork 11
D3 WebGL wrapper
The D3-WebGL wrapper is simple library in the glutils
module that make writing visualizations simply by using the D3 syntax.
To use the wrapper, you must first create a foreign object to attach the canvas to:
$('#myDiv').append('<foreignObject id="visCanvasFO"></foreignObject>');
$('#visCanvasFO')
.attr('x', MARGIN)
.attr('y', MARGIN)
.attr('width', WIDTH)
.attr('height', HEIGHT)
and then initialize the webgl environment:
var webgl = glutils.initWebGL('visCanvasFO', WIDTH, HEIGHT*10);
The webgl
variable allows you to access all the common objects and parameters in the webgl environment.
For example, you can set the camera position as follows:
webgl.camera.position.x = WIDTH/2;
webgl.camera.position.y = -HEIGHT*10/2;
webgl.disableHorizontalPanning();
The following example creates a set of 4 red circles. The syntax is (similar to) D3, but the objects created are webgl on HTML canvas.
var circles = glutils.selectAll()
.data([0,1,2,3])
.append('circle')
.attr('r', (d)=>d)
.attr('x', (d,i)=> 10 * i)
.attr('y', (d,i)=> 10 * i)
.style('fill', '#f00')
-
webgl.enableZoom(b:boolean)
- sets zoom with mousewheel. Default isfalse
-
webgl.enablePanning(b:boolean)
- sets panning with drag-and-drop. Default istrue
. -
enableHorizontalPanning(b:boolean)
- sets or disallows horizontal panning. Default istrue
The following snipped creates one circle for every element in the myData
array and stores them in a WebGLQueryElement
var someCircles:WebGLQueryElement = glutils.selectAll()
.data(myData)
.append('circle')
Currently, the wrapper supports the following visual elements and their stylings:
As in D3, you can then specify the individual appearances of each visual element
someCircles.append('circle')
.attr('x', function(l,i){return i;}))
.attr('y', function(l,i){return i;}))
.attr('r', 10)
.attr('r', someNumber) // radius
.style('fill', 'ff0000')
The 0,0 for a rectangle is its upper left corner.
.append('rect')
.attr('x', someNumber)
.attr('y', someNumber)
.attr('z', someNumber)
.attr('width', someNumber)
.attr('height', someNumber)
.attr('rotation', someNumber) // rotation in degree
.style('fill', '#ff0000')
.style('stroke', '#ff0000')
.style('opacity', '#ff0000')
The 0,0 for a circle is its center.
.append('circle')
.attr('x', someNumber)
.attr('y', someNumber)
.attr('z', someNumber)
.attr('r', someNumber) // radius
.attr('rotation', someNumber) // rotation in degree
.style('fill', '#ff0000')
.style('opacity', '#ff0000')
The 0,0 for a circle is its center.
.append('line')
.attr('x1', someNumber)
.attr('x2', someNumber)
.attr('y1', someNumber)
.attr('y2', someNumber)
.attr('z', someNumber)
.style('stroke', '#ff0000')
.style('stroke-width', someNumber)
.style('opacity', '#ff0000')
The 0,0 for a circle is its center.
.append('path')
.attr('x', someNumber)
.attr('x', someNumber)
.attr('z', someNumber)
.attr('r', someNumber) // radius
.attr('d', [points]) // each point must be in format {x:x, y:y}
.style('stroke', '#ff0000')
.style('stroke-width', someNumber)
.style('opacity', '#ff0000')
The 0,0 for a circle is its center.
.append('polygon')
.attr('x', someNumber)
.attr('x', someNumber)
.attr('z', someNumber)
.attr('r', someNumber) // radius
.attr('d', [points]) // each point must be in format {x:x, y:y}
.style('fill', '#ff0000')
.style('opacity', '#ff0000')
The 0,0 for a circle is its center.
.append('text')
.attr('x', someNumber)
.attr('x', someNumber)
.attr('z', someNumber)
.attr('r', someNumber) // radius
.text('myTextHere') // each point must be in format {x:x, y:y}
.style('stroke', '#ff0000')
.style('stroke-width', someNumber)
.style('opacity', '#ff0000')
As you may have noticed, certain things are missing, e.g.
- stokes on all objects
- a group element like
g
in D3.
Those are coming soon, if time permits.
Besides styling, you can attach mouse listeners:
someCircles
.on('mouseover', (d, i)=>{
// implement handler ...
)
.on('mouseout', (d, i)=>{
// implement handler ...
})
.on('mousemove', (d, i)=>{
// implement handler ...
})
.on('click', (d, i)=>{
// implement handler ...
})
To gain performance, rendering is triggered explicitly. So, each time you update your visualization, call:
webgl.render()