forked from heavysixer/d4
-
Notifications
You must be signed in to change notification settings - Fork 2
/
scales.js
120 lines (108 loc) · 3.49 KB
/
scales.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
(function() {
'use strict';
var extractValues = function(data, key) {
var values = data.map(function(obj) {
return obj.values.map(function(i) {
return i[key];
}.bind(this));
}.bind(this));
return d3.set(d3.merge(values)).values();
};
var rangeFor = function(chart, dimension) {
var padding = chart.padding;
// This may not be a very robust approach.
switch (dimension) {
case 'x':
return [padding.left, chart.width - padding.right];
case 'y':
return [chart.height - padding.bottom, padding.top];
case 'groups':
var groupDimension = chart.axes.groups.$dimension;
if (groupDimension === 'x') {
return [0, chart.axes.x.rangeBand()];
} else {
return [chart.axes.y.rangeBand(), 0];
}
break;
default:
return [];
}
};
var linearOrTimeScale = function(chart, data, dimension) {
var key = chart[dimension].$key;
var ext = d3.extent(d3.merge(data.map(function(obj) {
return d3.extent(obj.values, function(d) {
if (d4.isDate(d[key])) {
return d[key];
} else {
return d[key] + (d.y0 || 0);
}
});
})));
var axis = chart[dimension];
if (!axis.domain.$dirty) {
if (d4.isDate(ext[0])) {
var min = axis.$min || ext[0];
var max = axis.$max || ext[1];
axis.domain([min, max]);
} else {
axis.domain([Math.min(axis.$min || 0, ext[0]), axis.$max || ext[1]]);
}
}
if (!axis.range.$dirty) {
axis.range(rangeFor(chart, dimension));
}
if (!axis.clamp.$dirty) {
axis.clamp(true);
}
return chart[dimension];
};
/**
* Creates a linear scale for a dimension of a given chart.
* @name linearScaleForNestedData
* @param {Object} d4 chart object
* @param {Array} data array
* @param {string} string represnting a dimension e.g. `x`,`y`.
* @return {Object} Chart scale object
*/
d4.builder('linearScaleForNestedData', linearOrTimeScale);
/**
* Creates a time scale for a dimension of a given chart.
* @name timeScaleForNestedData
* @param {Object} d4 chart object
* @param {Array} data array
* @param {string} string represnting a dimension e.g. `x`,`y`.
* @return {Object} Chart scale object
*/
d4.builder('timeScaleForNestedData', linearOrTimeScale);
/**
* Creates an ordinal scale for a dimension of a given chart.
* @name ordinalScaleForNestedData
* @param {Object} d4 chart object
* @param {Array} data array
* @param {string} string represnting a dimension e.g. `x`,`y`.
* @return {Object} Chart scale object
*/
d4.builder('ordinalScaleForNestedData', function(chart, data, dimension) {
var parsedData = extractValues(data, chart[dimension].$key);
// Apply the padding to a `rangeRoundBands` d3 scale. Check for a custom
// or existing padding set by the scale, otherwise provide a default.
var bands;
if (chart[dimension + 'RoundBands']) {
bands = chart[dimension + 'RoundBands'];
} else if (chart[dimension].$roundBands) {
bands = chart[dimension].$roundBands;
} else {
bands = 0.3;
}
chart[dimension + 'RoundBands'] = bands;
var axis = chart[dimension];
if (!axis.domain.$dirty) {
axis.domain(parsedData);
}
if (!axis.rangeRoundBands.$dirty && !axis.rangePoints.$dirty && !axis.rangeBands.$dirty) {
axis.rangeRoundBands(rangeFor(chart, dimension), bands);
}
return axis;
});
}).call(this);