Improving D3 component event handling, responsiveness

This commit is contained in:
Colin McLeod
2015-06-07 15:42:59 -07:00
parent e876732ce0
commit b5e1c86a93
3 changed files with 42 additions and 27 deletions

View File

@@ -1,4 +1,4 @@
angular.module('app').directive('barChart', function () {
angular.module('app').directive('barChart', ['$window', function ($window) {
function bName (build) {
return build.buildName + '\n' + build.name;
@@ -7,11 +7,11 @@ angular.module('app').directive('barChart', function () {
var insertLinebreaks = function (d) {
var el = d3.select(this);
var words = d.split('\n');
el.text('').attr('y', -5);
el.text('').attr('y', -6);
for (var i = 0; i < words.length; i++) {
var tspan = el.append('tspan').text(words[i]);
if (i > 0) {
tspan.attr('x', -9).attr('dy', 10);
tspan.attr('x', -9).attr('dy', 12);
}
}
};
@@ -20,22 +20,23 @@ angular.module('app').directive('barChart', function () {
restrict: 'A',
scope:{
data: '=',
facet: '=',
height: '=',
width: '='
facet: '='
},
link: function(scope, element) {
var color = d3.scale.ordinal().range([ '#7b6888', '#6b486b', '#3182bd', '#a05d56', '#d0743c']),
width = scope.width,
labels = scope.facet.lbls,
fmt = scope.facet.fmt,
properties = scope.facet.props,
unit = scope.facet.unit,
margin = {top: 10, right: 20, bottom: 35, left: 150},
w = width - margin.left - margin.right;
y0 = d3.scale.ordinal(),
y1 = d3.scale.ordinal(),
x = d3.scale.linear(),
yAxis = d3.svg.axis().scale(y0).outerTickSize(0).orient('left'),
xAxis = d3.svg.axis().scale(x).ticks(5).outerTickSize(0).orient('bottom').tickFormat(d3.format('.2s'));;
// Create chart
var svg = d3.select(element[0]).append('svg').attr('width', width);
var svg = d3.select(element[0]).append('svg');
var vis = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
// Create and Add tooltip
@@ -44,17 +45,17 @@ angular.module('app').directive('barChart', function () {
.html(function(property, propertyIndex) {
return (labels? (labels[propertyIndex] + ': ') : '') + fmt(property.value) + ' ' + unit;
});
vis.call(tip);
// Create Y Axis SVG Elements
vis.append('g').attr('class', 'y axis');
vis.selectAll('g.y.axis g text').each(insertLinebreaks);
// Create X Axis SVG Elements
vis.append('g')
var xAxisLbl = vis.append('g')
.attr('class', 'x axis')
.append('text')
.attr('y', 30)
.attr('x', w/2)
.attr('dy', '.1em')
.style('text-anchor', 'middle')
.text(scope.facet.title + (unit? (' (' + unit + ')') : ''));
@@ -63,27 +64,31 @@ angular.module('app').directive('barChart', function () {
/**
* Watch for changes in the comparison array (ships added/removed, sorting)
*/
scope.$watchCollection('data', function() {
scope.$watchCollection('data', render);
angular.element($window).bind('orientationchange resize render', render);
function render() {
var data = scope.data,
height = 45 + (25 * data.length),
width = element[0].offsetWidth,
w = width - margin.left - margin.right;
height = 45 + (30 * data.length),
h = height - margin.top - margin.bottom,
maxVal = d3.max(data, function(d) { return d3.max(properties, function(p) {return d[p]; }); }),
y0 = d3.scale.ordinal().domain(data.map(bName)).rangeRoundBands([0, h],0.3),
y1 = d3.scale.ordinal().domain(properties).rangeRoundBands([0, y0.rangeBand()]),
x = d3.scale.linear().range([0, w]).domain([0, maxVal]),
yAxis = d3.svg.axis().scale(y0).outerTickSize(0).orient('left'),
xAxis = d3.svg.axis().scale(x).outerTickSize(0).orient('bottom').tickFormat(d3.format('.2s'));
// Update chart size
svg.attr('height', height);
svg.attr('width', width).attr('height', height);
// Remove existing elements
vis.selectAll('.ship').remove();
vis.selectAll('rect').remove();
// Update X & Y Axis
x.range([0, w]).domain([0, maxVal]);
y0.domain(data.map(bName)).rangeRoundBands([0, h],0.3);
y1.domain(properties).rangeRoundBands([0, y0.rangeBand()]);
vis.selectAll('.y.axis').call(yAxis);
vis.selectAll('.x.axis').attr('transform', 'translate(0,' + h + ')').call(xAxis);
xAxisLbl.attr('x', w/2);
// Update Y-Axis labels
vis.selectAll('g.y.axis g text').each(insertLinebreaks);
@@ -110,12 +115,13 @@ angular.module('app').directive('barChart', function () {
.on('mouseout', tip.hide)
.style('fill', function(d) { return color(d.name); });
});
}
scope.$on('$destroy', function() {
angular.element($window).unbind('orientationchange resize render', render);
tip.destroy(); // Remove the tooltip from the DOM
});
}
};
});
}]);