design pattern
for creating data
visualizations
with D3 & Angular
Nicholas Ortenzio
D3.js is a JavaScript library for manipulating documents based on data. D3 helps you bring data to life using HTML, SVG and CSS. D3’s emphasis on web standards gives you the full capabilities of modern browsers without tying yourself to a proprietary framework, combining powerful visualization components and a data-driven approach to DOM manipulation
AngularJS is what HTML would have been, had it been designed for building web-apps. Declarative templates with data-binding, MVW, MVVM, MVC, dependency injection and great testability story all implemented with pure client-side JavaScript
Initial Approach To using
d3 in an angular app
Put your D3 stuff inside a controller and call it a day.
Unhappy with this approach because
- It does not really take advantage of any Angular JS features
- Angular models / inputs that can alter are chart are not managed by D3
- No communication between frameworks
- Creating XML nodes in JavaScript drives me crazy
reasons why Creating XML nodes
in JavaScript drives me crazy
- Views and templates are a thing, its like the main reason for using Angular in the first place
- Does not intuitively describe the result
- Gets very messy and confusing
Alternative Approach
- Use D3 for the mathy stuff (if you even need it)
- Use Angular for the everything else
A simple bar chart
Notes
- ng-repeat through data. this is the easiest way to create distinct objects like rectangles, lines, circles and groups
- Use ng-attr-<attributename> or else the browser will complain
- If the data updates, so will the graph.
First Issue
Axes are a problem
Creating an axis returns a function that gets called directly from a selection.
Solutions
1. My initial approach was to create and Angular directive
Solutions
1. Create an Angular directive
This works I guess but I think it's over complicating the issue
Solutions
2. Alternative approach to rendering axes - Cheat
<g transform="translate(20,20)">
<g class="x axis" ng-attr-transform="translate(0, {{ height }})"></g>
<g class="y axis">
<text transform="rotate(-90)" y="6" dy=".71em" style="text-anchor:end;">Price</text>
</g>
</g>
$scope.xAxis = d3.svg.axis().scale($scope.x).orient("bottom");
$scope.yAxis = d3.svg.axis().scale($scope.y).orient("left");
$scope.xAxis(d3.select('.x.axis'));
$scope.yAxis(d3.select('.y.axis'));
This works just as well
Next Issue
Okay so barcharts and scatter plots are easy, but what about
charts that arent a 1:1 representation of data?
- Line charts
- Area charts
- Polygons
- Topographic charts
- Hexagonal Binning
- Heat maps
- etc...
Solution
Many chart types work by accepting data and returning a path
area
area = d3.svg.area()
.x(function(d) { return $scope.x(d.date); })
.y0($scope.height)
.y1(function(d) { return $scope.y(d.close); });
$scope.areaPath = area($scope.data);
geopath = d3.geo.path().projection(projection);
$scope.ocean.path = path($scope.ocean.data);
...which you can render
<path d="{{ path }}" />
Hexbin
$scope.hexbin = d3.hexbin()
.size([width, height])
.radius(10);
<path ng-repeat="(i, hex) in hexs"
ng-attr-d="{{ hexbin.hexagon() }}"
ng-attr-transform="translate({{ hex.x }}, {{ hex.y}})"
ng-attr-style="fill: {{ color(hex.length) }}"
class="hexagon" />
Basically, having a deep understanding of how all
the D3 chart types work
is key to using them without D3
Further exploration
- Brushes
- SVG view box
- Transitions with ng-animate
- Deeper understanding of Joins (enter / update / exit)
Thank you
Slides
https://slides.com/nonononono/using-d3-with-angular-js/
Examples
Source
Using D3 with Angular JS
By nonononono
Using D3 with Angular JS
Presentation for Manhattan JS on an alternative way to use D3 js in combination with Angular to create visualizations and graphs
- 6,233