OLD | NEW |
| (Empty) |
1 // | |
2 // Copyright 2014 Google Inc. All rights reserved. | |
3 // | |
4 // Use of this source code is governed by a BSD-style | |
5 // license that can be found in the LICENSE file or at | |
6 // https://developers.google.com/open-source/licenses/bsd | |
7 // | |
8 | |
9 part of charted.charts; | |
10 | |
11 /// A behavior that draws marking lines on the chart. | |
12 class AxisLabelTooltip implements ChartBehavior { | |
13 static const _AXIS_SELECTOR = '.measure-axis-group,.dimension-axis-group'; | |
14 | |
15 SubscriptionsDisposer _disposer = new SubscriptionsDisposer(); | |
16 StreamSubscription _axesChangeSubscription; | |
17 CartesianArea _area; | |
18 Element _tooltipRoot; | |
19 | |
20 math.Rectangle _hostAreaRect; | |
21 math.Rectangle _renderAreaRect; | |
22 | |
23 void init(ChartArea area, Selection upper, Selection lower) { | |
24 if (area is! CartesianArea) return; | |
25 _area = area; | |
26 _axesChangeSubscription = | |
27 _area.onChartAxesUpdated.listen((_) => _subscribe()); | |
28 | |
29 // Axis tooltip requires host to be position: relative. | |
30 area.host.style.position = 'relative'; | |
31 } | |
32 | |
33 void dispose() { | |
34 _disposer.dispose(); | |
35 if (_tooltipRoot != null) _tooltipRoot.remove(); | |
36 } | |
37 | |
38 void _subscribe() { | |
39 var elements = _area.host.querySelectorAll(_AXIS_SELECTOR); | |
40 _disposer.dispose(); | |
41 _disposer.addAll( | |
42 elements.map((x) => x.onMouseOver.listen(_handleMouseOver))); | |
43 _disposer.addAll( | |
44 elements.map((x) => x.onMouseOut.listen(_handleMouseOut))); | |
45 } | |
46 | |
47 void _handleMouseOver(MouseEvent e) { | |
48 Element target = e.target; | |
49 if (!target.dataset.containsKey('detail')) return; | |
50 ensureTooltipRoot(); | |
51 ensureRenderAreaRect(); | |
52 | |
53 _tooltipRoot.text = target.dataset['detail']; | |
54 var position = computeTooltipPosition( | |
55 target.getBoundingClientRect(), | |
56 _tooltipRoot.getBoundingClientRect(), | |
57 _renderAreaRect); | |
58 | |
59 _tooltipRoot.style | |
60 ..left = '${position.x}px' | |
61 ..top = '${position.y}px' | |
62 ..opacity = '1' | |
63 ..visibility = 'visible'; | |
64 } | |
65 | |
66 void _handleMouseOut(MouseEvent e) { | |
67 Element target = e.target; | |
68 if (!target.dataset.containsKey('detail')) return; | |
69 if (_tooltipRoot != null) { | |
70 _tooltipRoot.style | |
71 ..opacity = '0' | |
72 ..visibility = 'hidden'; | |
73 } | |
74 } | |
75 | |
76 void ensureTooltipRoot() { | |
77 if (_tooltipRoot == null) { | |
78 _tooltipRoot = new Element.tag('div') | |
79 ..style.position = 'absolute' | |
80 ..attributes['dir'] = _area.config.isRTL ? 'rtl' : '' | |
81 ..classes.add('chart-axis-label-tooltip'); | |
82 if (_area.config.isRTL) { | |
83 _tooltipRoot.classes.add('rtl'); | |
84 } else { | |
85 _tooltipRoot.classes.remove('rtl'); | |
86 } | |
87 _area.host.append(_tooltipRoot); | |
88 } | |
89 } | |
90 | |
91 void ensureRenderAreaRect() { | |
92 var layout = _area.layout; | |
93 _hostAreaRect = _area.host.getBoundingClientRect(); | |
94 _renderAreaRect = new math.Rectangle( | |
95 _hostAreaRect.left + layout.chartArea.x + layout.renderArea.x, | |
96 _hostAreaRect.top + layout.chartArea.y + layout.renderArea.y, | |
97 layout.renderArea.width, layout.renderArea.height); | |
98 } | |
99 | |
100 /// Computes the ideal tooltip position based on orientation. | |
101 math.Point computeTooltipPosition(math.Rectangle label, | |
102 math.Rectangle tooltip, math.Rectangle renderArea) { | |
103 var x = label.left + (label.width - tooltip.width) / 2, | |
104 y = label.top + (label.height - tooltip.height) / 2; | |
105 | |
106 if (x + tooltip.width > renderArea.right) { | |
107 x = renderArea.right - tooltip.width; | |
108 } else if (x < renderArea.left) { | |
109 x = renderArea.left; | |
110 } | |
111 | |
112 if (y + tooltip.height > renderArea.bottom) { | |
113 y = renderArea.bottom - tooltip.height; | |
114 } else if (y < renderArea.top) { | |
115 y = renderArea.top; | |
116 } | |
117 | |
118 return new math.Point(x - _hostAreaRect.left, y - _hostAreaRect.top); | |
119 } | |
120 } | |
OLD | NEW |