-
Notifications
You must be signed in to change notification settings - Fork 46
/
x-axis.js
132 lines (120 loc) · 4.49 KB
/
x-axis.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
(function() {
'use strict';
/* This feature creates an xAxis for use within d4. There are a variety of
* accessors described below which modify the behavior and apperance of the axis.
*
*##### Accessors
*
* `axis` - The d3 axis object itself.
* `innerTickSize` - see: https://github.com/mbostock/d3/wiki/SVG-Axes#innerTickSize
* `orient` - see: https://github.com/mbostock/d3/wiki/SVG-Axes#orient
* `outerTickSize`- see: https://github.com/mbostock/d3/wiki/SVG-Axes#outerTickSize
* `scale` - see: https://github.com/mbostock/d3/wiki/SVG-Axes#scale
* `stagger` - (true | false) determines if the axis should stagger overlapping text (true by default)
* `tickFormat` - see: https://github.com/mbostock/d3/wiki/SVG-Axes#tickFormat
* `tickPadding` - see: https://github.com/mbostock/d3/wiki/SVG-Axes#tickPadding
* `tickSize` - see: https://github.com/mbostock/d3/wiki/SVG-Axes#tickSize
* `tickSubdivide`- see: https://github.com/mbostock/d3/wiki/SVG-Axes#tickSubdivide
* `tickValues` - see: https://github.com/mbostock/d3/wiki/SVG-Axes#tickValues
* `ticks` - see: https://github.com/mbostock/d3/wiki/SVG-Axes#ticks
*
*
* var chart = d4.charts.groupedColumn()
* .using('yAxis', function(axis){
*
* // adjust the number of tick marks based on the height of the chart
* axis.ticks($('#example').height()/20);
*
* // set the inner and outer tick sizes
* axis.tickSize(10,5);
*
* // adjust the tick padding
* axis.tickPadding(5);
*
* })
* .using('xAxis', function(axis){
*
* // position the tickmarks on the top of the axis line
* axis.orient('top');
*
* // move the axis to the top of the chart.
* axis.align('top');
* })
*
* @name xAxis
*/
d4.feature('xAxis', function(name) {
var axis = d3.svg.axis()
.orient('bottom')
.tickPadding(10)
.tickSize(0);
var textRect = function(text, klasses) {
var rect = d4.helpers.textSize(text, klasses);
rect.text = text;
return rect;
};
var positionText = function(obj, aligned, klass, scaleId) {
if (obj.text) {
var axis = this.container.selectAll('.' + scaleId + '.axis');
var axisBB = axis.node().getBBox();
var textHeight = obj.height * 0.8;
var text = axis.append('text')
.text(obj.text)
.attr('class', '' + klass);
if (aligned.toLowerCase() === 'bottom') {
text.attr('transform', 'translate(0,' + (axisBB.height + textHeight) + ')');
} else {
text.attr('transform', 'translate(0,' + (axisBB.y - (textHeight / 2)) + ')');
}
}
};
var alignAxis = function(align, axis) {
switch (true) {
case align.toLowerCase() === 'top':
axis.attr('transform', 'translate(0,0)');
break;
case align.toLowerCase() === 'bottom':
axis.attr('transform', 'translate(0,' + this.height + ')');
break;
}
};
var obj = {
accessors: {
align: 'bottom',
stagger: true,
subtitle: undefined,
title: undefined,
scaleId: function() {
return 'x';
}
},
proxies: [{
target: axis
}],
render: function(scope, data, selection) {
var scaleId = d4.functor(scope.accessors.scaleId).bind(this)();
scope.scale(this[scaleId]);
var title = textRect(d4.functor(scope.accessors.title).bind(this)(), 'title');
var subtitle = textRect(d4.functor(scope.accessors.subtitle).bind(this)(), 'subtitle');
var aligned = d4.functor(scope.accessors.align).bind(this)();
var group = d4.appendOnce(selection, 'g.' + scaleId + '.axis.' + name)
.attr('data-scale', this[scaleId].$scale)
.call(axis);
alignAxis.bind(this)(aligned, group);
if (d4.functor(scope.accessors.stagger).bind(this)()) {
// FIXME: This should be moved into a helper injected using DI.
group.selectAll('.tick text').call(d4.helpers.staggerTextVertically, 1);
}
if (aligned === 'top') {
positionText.bind(this)(subtitle, aligned, 'subtitle', scaleId);
positionText.bind(this)(title, aligned, 'title', scaleId);
} else {
positionText.bind(this)(title, aligned, 'title', scaleId);
positionText.bind(this)(subtitle, aligned, 'subtitle', scaleId);
}
return group;
}
};
return obj;
});
}).call(this);