/
Bound.js
80 lines (67 loc) · 2.27 KB
/
Bound.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
import {AxisRole, Group, LegendRole, TitleRole} from './constants';
import {Transform} from 'vega-dataflow';
import {Marks, boundClip} from 'vega-scenegraph';
import {inherits} from 'vega-util';
/**
* Calculate bounding boxes for scenegraph items.
* @constructor
* @param {object} params - The parameters for this operator.
* @param {object} params.mark - The scenegraph mark instance to bound.
*/
export default function Bound(params) {
Transform.call(this, null, params);
}
inherits(Bound, Transform, {
transform(_, pulse) {
const view = pulse.dataflow,
mark = _.mark,
type = mark.marktype,
entry = Marks[type],
bound = entry.bound;
let markBounds = mark.bounds, rebound;
if (entry.nested) {
// multi-item marks have a single bounds instance
if (mark.items.length) view.dirty(mark.items[0]);
markBounds = boundItem(mark, bound);
mark.items.forEach(item => {
item.bounds.clear().union(markBounds);
});
}
else if (type === Group || _.modified()) {
// operator parameters modified -> re-bound all items
// updates group bounds in response to modified group content
pulse.visit(pulse.MOD, item => view.dirty(item));
markBounds.clear();
mark.items.forEach(item => markBounds.union(boundItem(item, bound)));
// force reflow for axes/legends/titles to propagate any layout changes
switch (mark.role) {
case AxisRole:
case LegendRole:
case TitleRole:
pulse.reflow();
}
}
else {
// incrementally update bounds, re-bound mark as needed
rebound = pulse.changed(pulse.REM);
pulse.visit(pulse.ADD, item => {
markBounds.union(boundItem(item, bound));
});
pulse.visit(pulse.MOD, item => {
rebound = rebound || markBounds.alignsWith(item.bounds);
view.dirty(item);
markBounds.union(boundItem(item, bound));
});
if (rebound) {
markBounds.clear();
mark.items.forEach(item => markBounds.union(item.bounds));
}
}
// ensure mark bounds do not exceed any clipping region
boundClip(mark);
return pulse.modifies('bounds');
}
});
function boundItem(item, bound, opt) {
return bound(item.bounds.clear(), item, opt);
}