Skip to content

Instantly share code, notes, and snippets.

@deborre
Last active January 7, 2016 10:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save deborre/42139fd6538a96cb72f3 to your computer and use it in GitHub Desktop.
Save deborre/42139fd6538a96cb72f3 to your computer and use it in GitHub Desktop.
viz module for custom d3.js viz framework
/*
We're using a pluggable module for each type of visualisation.
These are setup using a standard architecture and can make use of all the methods
and services supplied by the common visualisationsController.
*/
vizModule
/*
Make sure to utilise what your frameworks have to offer i.e. D3 methods for manipulating data structure and format
-> https://github.com/mbostock/d3/wiki/Arrays
-> https://github.com/mbostock/d3/wiki/Math
-> https://github.com/mbostock/d3/wiki/Formatting
-> https://github.com/mbostock/d3/wiki/Layouts
*/
vizModule.preprocessData = function( $rawData ){
/*
As an example we could make sure the data elements this type of visualisation depends on are actually present
within the data available.
*/
if( typeof $rawData !== 'object' || typeof $rawData.nodes !== 'object' )
return false;
var $processedData = $rawData;
/*
Additional structuring or filtering of the data could happen here.
*/
vizModule.processedData = $processedData;
return $processedData;
};
/*
This is where we set up functions to plot certain elements, create axis -> https://github.com/mbostock/d3/wiki/SVG-Axes
insert the basic DOM elements needed for this type of viz and generally do all operations that should only have to be
carried out once to enable painting.
*/
vizModule.setupGraph = function(){
/*
We can invoke methods from the core of the framework to make use of commonly used operations like clearing the contents
of the element we are drawing the viz in before setup.
*/
visualisationsController.clearCanvas();
/*
The setup method can also be used to create any additional methods we will need to paint the viz later.
For example we can prepare our scales and axis here.
*/
vizModule.xScale = d3.scale.linear().range(0,100);
vizModule.xAxis = d3.svg.axis().scale(vizModule.xScale).orient("bottom").ticks(10);
/*
Lets assume that visualisationsController.canvas holds the DOM element we are using to hold our viz and it is
a simple DIV we will use as a container. We now want to insert our blank SVG element to draw on later.
*/
vizModule.svg = d3.select(visualisationsController.canvas).append("svg");
/*
Since we have our SVG all setup know we can alreay draw our xAxis as we will not want to have to repeat that step
everytime we paint the other viz elements.
*/
vizModule.svg.append("g").attr("class","x-axis").call(vizModule.xAxis);
/*
Returning true is important to our method chaining we discussed earlier in the core of the framework.
It lets us check that steps depending on each other were executed correctly.
*/
return true;
};
/*
This is where the final magic happens and we actually draw our plots.
Make sure you understand and utilises D3 data joins and make use of .enter() and .exit() methods.
This method will be called whenever there is a change in data or the plot needs to be redrawn.
So we want to make sure to only run operations that are necessary to avoid repetition.
-> Great introduction here: http://bost.ocks.org/mike/join/
*/
vizModule.paintGraph = function(){
/*
Lets include some nodes in our SVG, we can do that by making use of the D3 data join methods.
Here we basically join HTML elements with the CSS class ".node" to our data structure.
*/
vizModule.nodes = vizModule.svg.selectAll(".node").data(vizModule.processedData.nodes);
/*
If there is too little corresponding HTML elements for our dataset we add more.
*/
vizModule.nodes.enter().append("circle").attr("class","node");
/*
And if there is too many corresponding HTML elements for our dataset we can remove them.
*/
vizModule.nodes.exit().remove();
/*
Now that we have exactly the right amount of DOM elements to match our data we can manipulate them to represent
our data. In this case lets position the circles we we have appended to the SVG element along our x-axis.
*/
vizModule.nodes.attr("cx",function( $nodeData ){
return( vizModule.xScale( $nodeData.x ) );
});
/*
Again we can finish the painting method by returning true and letting the core of the framework know that
everything went smoothly.
*/
return true;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment