Skip to content
This repository has been archived by the owner on Jul 18, 2022. It is now read-only.

D3 WebGL wrapper

Benjamin edited this page Aug 24, 2016 · 1 revision

The D3-WebGL wrapper is simple library in the glutils module that make writing visualizations simply by using the D3 syntax.

Setup and initialization

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')

Parameters

  • webgl.enableZoom(b:boolean) - sets zoom with mousewheel. Default is false
  • webgl.enablePanning(b:boolean) - sets panning with drag-and-drop. Default is true.
  • enableHorizontalPanning(b:boolean) - sets or disallows horizontal panning. Default is true

Binding data to visual elements

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:

Create Visuals

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')

Rectangle

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')

Circle

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')

Line

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')

Path

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')

Polygon

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')

Text

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.

Listeners

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 ...
    })

Render

To gain performance, rendering is triggered explicitly. So, each time you update your visualization, call:

    webgl.render()