@perspective-dev/viewer-charts 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +193 -0
- package/dist/cdn/perspective-viewer-charts.js +3 -0
- package/dist/cdn/perspective-viewer-charts.js.map +7 -0
- package/dist/esm/axis/axis-primitives.d.ts +24 -0
- package/dist/esm/axis/bar-axis.d.ts +51 -0
- package/dist/esm/axis/canvas.d.ts +24 -0
- package/dist/esm/axis/categorical-axis-core.d.ts +42 -0
- package/dist/esm/axis/categorical-axis.d.ts +27 -0
- package/dist/esm/axis/facet-chrome.d.ts +13 -0
- package/dist/esm/axis/label-geometry.d.ts +41 -0
- package/dist/esm/axis/legend.d.ts +44 -0
- package/dist/esm/axis/numeric-axis.d.ts +20 -0
- package/dist/esm/charts/candlestick/candlestick-build.d.ts +129 -0
- package/dist/esm/charts/candlestick/candlestick-interact.d.ts +10 -0
- package/dist/esm/charts/candlestick/candlestick-render.d.ts +24 -0
- package/dist/esm/charts/candlestick/candlestick.d.ts +144 -0
- package/dist/esm/charts/candlestick/glyphs/draw-candlesticks.d.ts +36 -0
- package/dist/esm/charts/candlestick/glyphs/draw-ohlc.d.ts +33 -0
- package/dist/esm/charts/canvas-types.d.ts +15 -0
- package/dist/esm/charts/cartesian/cartesian-build.d.ts +14 -0
- package/dist/esm/charts/cartesian/cartesian-interact.d.ts +20 -0
- package/dist/esm/charts/cartesian/cartesian-render.d.ts +26 -0
- package/dist/esm/charts/cartesian/cartesian.d.ts +239 -0
- package/dist/esm/charts/cartesian/glyph.d.ts +53 -0
- package/dist/esm/charts/cartesian/glyphs/density.d.ts +142 -0
- package/dist/esm/charts/cartesian/glyphs/lines.d.ts +23 -0
- package/dist/esm/charts/cartesian/glyphs/points.d.ts +24 -0
- package/dist/esm/charts/cartesian/label-interner.d.ts +21 -0
- package/dist/esm/charts/cartesian/tooltip-lines.d.ts +11 -0
- package/dist/esm/charts/chart-base.d.ts +402 -0
- package/dist/esm/charts/chart.d.ts +338 -0
- package/dist/esm/charts/common/band-layout.d.ts +32 -0
- package/dist/esm/charts/common/categorical-y-chart.d.ts +53 -0
- package/dist/esm/charts/common/category-axis-resolver.d.ts +90 -0
- package/dist/esm/charts/common/chrome-cache.d.ts +18 -0
- package/dist/esm/charts/common/draw-tooltip-box.d.ts +9 -0
- package/dist/esm/charts/common/leaf-color.d.ts +33 -0
- package/dist/esm/charts/common/node-store.d.ts +81 -0
- package/dist/esm/charts/common/tree-chart.d.ts +48 -0
- package/dist/esm/charts/common/tree-chrome.d.ts +31 -0
- package/dist/esm/charts/common/tree-data.d.ts +54 -0
- package/dist/esm/charts/common/visible-extent.d.ts +51 -0
- package/dist/esm/charts/heatmap/heatmap-build.d.ts +86 -0
- package/dist/esm/charts/heatmap/heatmap-interact.d.ts +19 -0
- package/dist/esm/charts/heatmap/heatmap-render.d.ts +19 -0
- package/dist/esm/charts/heatmap/heatmap-y-axis.d.ts +46 -0
- package/dist/esm/charts/heatmap/heatmap.d.ts +117 -0
- package/dist/esm/charts/map/map.d.ts +67 -0
- package/dist/esm/charts/registry.d.ts +14 -0
- package/dist/esm/charts/series/glyphs/draw-areas.d.ts +30 -0
- package/dist/esm/charts/series/glyphs/draw-bars.d.ts +15 -0
- package/dist/esm/charts/series/glyphs/draw-lines.d.ts +34 -0
- package/dist/esm/charts/series/glyphs/draw-scatter.d.ts +33 -0
- package/dist/esm/charts/series/series-build.d.ts +228 -0
- package/dist/esm/charts/series/series-interact.d.ts +35 -0
- package/dist/esm/charts/series/series-render.d.ts +41 -0
- package/dist/esm/charts/series/series-type.d.ts +49 -0
- package/dist/esm/charts/series/series.d.ts +317 -0
- package/dist/esm/charts/sunburst/sunburst-interact.d.ts +7 -0
- package/dist/esm/charts/sunburst/sunburst-layout.d.ts +33 -0
- package/dist/esm/charts/sunburst/sunburst-render.d.ts +22 -0
- package/dist/esm/charts/sunburst/sunburst.d.ts +85 -0
- package/dist/esm/charts/treemap/treemap-interact.d.ts +12 -0
- package/dist/esm/charts/treemap/treemap-layout.d.ts +28 -0
- package/dist/esm/charts/treemap/treemap-render.d.ts +18 -0
- package/dist/esm/charts/treemap/treemap.d.ts +74 -0
- package/dist/esm/config.d.ts +27 -0
- package/dist/esm/data/lazy-row.d.ts +32 -0
- package/dist/esm/data/split-groups.d.ts +20 -0
- package/dist/esm/data/view-reader.d.ts +35 -0
- package/dist/esm/event-detail.d.ts +28 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/interaction/hit-test.d.ts +30 -0
- package/dist/esm/interaction/host-sink-dom.d.ts +19 -0
- package/dist/esm/interaction/host-sink-message.d.ts +46 -0
- package/dist/esm/interaction/lazy-tooltip.d.ts +61 -0
- package/dist/esm/interaction/raw-event-forwarder.d.ts +27 -0
- package/dist/esm/interaction/spatial-grid.d.ts +15 -0
- package/dist/esm/interaction/tooltip-controller.d.ts +193 -0
- package/dist/esm/interaction/zoom-controller.d.ts +106 -0
- package/dist/esm/interaction/zoom-router.d.ts +48 -0
- package/dist/esm/layout/facet-grid.d.ts +126 -0
- package/dist/esm/layout/plot-layout.d.ts +104 -0
- package/dist/esm/layout/ticks.d.ts +17 -0
- package/dist/esm/map/mercator.d.ts +102 -0
- package/dist/esm/map/tile-cache.d.ts +38 -0
- package/dist/esm/map/tile-layer.d.ts +66 -0
- package/dist/esm/map/tile-loader.d.ts +52 -0
- package/dist/esm/map/tile-source.d.ts +66 -0
- package/dist/esm/perspective-viewer-charts.js +3 -0
- package/dist/esm/perspective-viewer-charts.js.map +7 -0
- package/dist/esm/plugin/charts.d.ts +40 -0
- package/dist/esm/plugin/plugin.d.ts +95 -0
- package/dist/esm/render/scheduler.d.ts +41 -0
- package/dist/esm/theme/gradient.d.ts +48 -0
- package/dist/esm/theme/palette.d.ts +13 -0
- package/dist/esm/theme/theme-snapshot.d.ts +7 -0
- package/dist/esm/theme/theme.d.ts +53 -0
- package/dist/esm/transport/protocol.d.ts +430 -0
- package/dist/esm/transport/renderer-transport.d.ts +201 -0
- package/dist/esm/utils/css.d.ts +1 -0
- package/dist/esm/utils/font-snapshot.d.ts +50 -0
- package/dist/esm/webgl/buffer-pool.d.ts +62 -0
- package/dist/esm/webgl/context-manager.d.ts +184 -0
- package/dist/esm/webgl/gradient-texture.d.ts +17 -0
- package/dist/esm/webgl/instanced-attrs.d.ts +44 -0
- package/dist/esm/webgl/plot-frame.d.ts +39 -0
- package/dist/esm/webgl/program-cache.d.ts +13 -0
- package/dist/esm/webgl/shader-manifest.d.ts +53 -0
- package/dist/esm/webgl/shader-registry.d.ts +22 -0
- package/dist/esm/worker/boot.d.ts +0 -0
- package/dist/esm/worker/dispatch.d.ts +9 -0
- package/dist/esm/worker/font-loader.d.ts +2 -0
- package/dist/esm/worker/renderer.worker.d.ts +115 -0
- package/dist/esm/worker/session-host.d.ts +26 -0
- package/package.json +47 -0
- package/src/css/perspective-viewer-charts.css +95 -0
- package/src/ts/axis/axis-primitives.ts +125 -0
- package/src/ts/axis/bar-axis.ts +345 -0
- package/src/ts/axis/canvas.ts +64 -0
- package/src/ts/axis/categorical-axis-core.ts +125 -0
- package/src/ts/axis/categorical-axis.ts +716 -0
- package/src/ts/axis/facet-chrome.ts +42 -0
- package/src/ts/axis/label-geometry.ts +188 -0
- package/src/ts/axis/legend.ts +218 -0
- package/src/ts/axis/numeric-axis.ts +353 -0
- package/src/ts/charts/candlestick/candlestick-build.ts +516 -0
- package/src/ts/charts/candlestick/candlestick-interact.ts +256 -0
- package/src/ts/charts/candlestick/candlestick-render.ts +387 -0
- package/src/ts/charts/candlestick/candlestick.ts +367 -0
- package/src/ts/charts/candlestick/glyphs/draw-candlesticks.ts +432 -0
- package/src/ts/charts/candlestick/glyphs/draw-ohlc.ts +317 -0
- package/src/ts/charts/canvas-types.ts +30 -0
- package/src/ts/charts/cartesian/cartesian-build.ts +616 -0
- package/src/ts/charts/cartesian/cartesian-interact.ts +355 -0
- package/src/ts/charts/cartesian/cartesian-render.ts +948 -0
- package/src/ts/charts/cartesian/cartesian.ts +469 -0
- package/src/ts/charts/cartesian/glyph.ts +81 -0
- package/src/ts/charts/cartesian/glyphs/density.ts +1263 -0
- package/src/ts/charts/cartesian/glyphs/lines.ts +320 -0
- package/src/ts/charts/cartesian/glyphs/points.ts +239 -0
- package/src/ts/charts/cartesian/label-interner.ts +56 -0
- package/src/ts/charts/cartesian/tooltip-lines.ts +80 -0
- package/src/ts/charts/chart-base.ts +840 -0
- package/src/ts/charts/chart.ts +427 -0
- package/src/ts/charts/common/band-layout.ts +63 -0
- package/src/ts/charts/common/categorical-y-chart.ts +81 -0
- package/src/ts/charts/common/category-axis-resolver.ts +314 -0
- package/src/ts/charts/common/chrome-cache.ts +79 -0
- package/src/ts/charts/common/draw-tooltip-box.ts +84 -0
- package/src/ts/charts/common/leaf-color.ts +92 -0
- package/src/ts/charts/common/node-store.ts +235 -0
- package/src/ts/charts/common/tree-chart.ts +76 -0
- package/src/ts/charts/common/tree-chrome.ts +123 -0
- package/src/ts/charts/common/tree-data.ts +623 -0
- package/src/ts/charts/common/visible-extent.ts +112 -0
- package/src/ts/charts/heatmap/heatmap-build.ts +426 -0
- package/src/ts/charts/heatmap/heatmap-interact.ts +274 -0
- package/src/ts/charts/heatmap/heatmap-render.ts +815 -0
- package/src/ts/charts/heatmap/heatmap-y-axis.ts +351 -0
- package/src/ts/charts/heatmap/heatmap.ts +368 -0
- package/src/ts/charts/map/map.ts +201 -0
- package/src/ts/charts/registry.ts +65 -0
- package/src/ts/charts/series/glyphs/draw-areas.ts +331 -0
- package/src/ts/charts/series/glyphs/draw-bars.ts +113 -0
- package/src/ts/charts/series/glyphs/draw-lines.ts +320 -0
- package/src/ts/charts/series/glyphs/draw-scatter.ts +328 -0
- package/src/ts/charts/series/series-build.ts +848 -0
- package/src/ts/charts/series/series-interact.ts +604 -0
- package/src/ts/charts/series/series-render.ts +1109 -0
- package/src/ts/charts/series/series-type.ts +99 -0
- package/src/ts/charts/series/series.ts +794 -0
- package/src/ts/charts/sunburst/sunburst-interact.ts +460 -0
- package/src/ts/charts/sunburst/sunburst-layout.ts +238 -0
- package/src/ts/charts/sunburst/sunburst-render.ts +887 -0
- package/src/ts/charts/sunburst/sunburst.ts +248 -0
- package/src/ts/charts/treemap/treemap-interact.ts +445 -0
- package/src/ts/charts/treemap/treemap-layout.ts +328 -0
- package/src/ts/charts/treemap/treemap-render.ts +886 -0
- package/src/ts/charts/treemap/treemap.ts +247 -0
- package/src/ts/config.ts +41 -0
- package/src/ts/data/lazy-row.ts +140 -0
- package/src/ts/data/split-groups.ts +97 -0
- package/src/ts/data/view-reader.ts +107 -0
- package/src/ts/event-detail.ts +44 -0
- package/src/ts/index.ts +53 -0
- package/src/ts/interaction/hit-test.ts +106 -0
- package/src/ts/interaction/host-sink-dom.ts +85 -0
- package/src/ts/interaction/host-sink-message.ts +75 -0
- package/src/ts/interaction/lazy-tooltip.ts +102 -0
- package/src/ts/interaction/raw-event-forwarder.ts +175 -0
- package/src/ts/interaction/spatial-grid.ts +100 -0
- package/src/ts/interaction/tooltip-controller.ts +407 -0
- package/src/ts/interaction/zoom-controller.ts +468 -0
- package/src/ts/interaction/zoom-router.ts +230 -0
- package/src/ts/layout/facet-grid.ts +346 -0
- package/src/ts/layout/plot-layout.ts +277 -0
- package/src/ts/layout/ticks.ts +168 -0
- package/src/ts/map/mercator.ts +204 -0
- package/src/ts/map/tile-cache.ts +96 -0
- package/src/ts/map/tile-layer.ts +382 -0
- package/src/ts/map/tile-loader.ts +143 -0
- package/src/ts/map/tile-source.ts +156 -0
- package/src/ts/plugin/charts.ts +286 -0
- package/src/ts/plugin/plugin.ts +668 -0
- package/src/ts/render/scheduler.ts +339 -0
- package/src/ts/shaders/area.frag.glsl +20 -0
- package/src/ts/shaders/area.vert.glsl +19 -0
- package/src/ts/shaders/bar.frag.glsl +25 -0
- package/src/ts/shaders/bar.vert.glsl +60 -0
- package/src/ts/shaders/candlestick-body.frag.glsl +19 -0
- package/src/ts/shaders/candlestick-body.vert.glsl +34 -0
- package/src/ts/shaders/density-extreme.frag.glsl +30 -0
- package/src/ts/shaders/density-mrt.frag.glsl +44 -0
- package/src/ts/shaders/density-mrt.vert.glsl +48 -0
- package/src/ts/shaders/density-resolve.frag.glsl +89 -0
- package/src/ts/shaders/density-resolve.vert.glsl +23 -0
- package/src/ts/shaders/density-splat.frag.glsl +34 -0
- package/src/ts/shaders/density-splat.vert.glsl +52 -0
- package/src/ts/shaders/gridline.frag.glsl +18 -0
- package/src/ts/shaders/gridline.vert.glsl +18 -0
- package/src/ts/shaders/heatmap.frag.glsl +23 -0
- package/src/ts/shaders/heatmap.vert.glsl +42 -0
- package/src/ts/shaders/line-uniform.frag.glsl +26 -0
- package/src/ts/shaders/line-uniform.vert.glsl +54 -0
- package/src/ts/shaders/line.frag.glsl +28 -0
- package/src/ts/shaders/line.vert.glsl +87 -0
- package/src/ts/shaders/scatter.frag.glsl +39 -0
- package/src/ts/shaders/scatter.vert.glsl +67 -0
- package/src/ts/shaders/sunburst-arc.frag.glsl +19 -0
- package/src/ts/shaders/sunburst-arc.vert.glsl +79 -0
- package/src/ts/shaders/tile.frag.glsl +27 -0
- package/src/ts/shaders/tile.vert.glsl +35 -0
- package/src/ts/shaders/treemap.frag.glsl +19 -0
- package/src/ts/shaders/treemap.vert.glsl +25 -0
- package/src/ts/shaders/y-scatter.frag.glsl +30 -0
- package/src/ts/shaders/y-scatter.vert.glsl +31 -0
- package/src/ts/theme/gradient.ts +312 -0
- package/src/ts/theme/palette.ts +64 -0
- package/src/ts/theme/theme-snapshot.ts +66 -0
- package/src/ts/theme/theme.ts +166 -0
- package/src/ts/transport/protocol.ts +497 -0
- package/src/ts/transport/renderer-transport.ts +788 -0
- package/src/ts/utils/css.ts +36 -0
- package/src/ts/utils/font-snapshot.ts +159 -0
- package/src/ts/webgl/buffer-pool.ts +163 -0
- package/src/ts/webgl/context-manager.ts +414 -0
- package/src/ts/webgl/gradient-texture.ts +84 -0
- package/src/ts/webgl/instanced-attrs.ts +139 -0
- package/src/ts/webgl/plot-frame.ts +91 -0
- package/src/ts/webgl/program-cache.ts +46 -0
- package/src/ts/webgl/shader-manifest.ts +148 -0
- package/src/ts/webgl/shader-registry.ts +97 -0
- package/src/ts/worker/boot.ts +22 -0
- package/src/ts/worker/dispatch.ts +99 -0
- package/src/ts/worker/font-loader.ts +89 -0
- package/src/ts/worker/renderer.worker.ts +734 -0
- package/src/ts/worker/session-host.ts +118 -0
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
import type { SeriesChart } from "./series";
|
|
14
|
+
import {
|
|
15
|
+
BAR_TYPE_BAR,
|
|
16
|
+
BAR_TYPE_AREA,
|
|
17
|
+
readBarRecord,
|
|
18
|
+
type SeriesChartRecord,
|
|
19
|
+
} from "./series-build";
|
|
20
|
+
import {
|
|
21
|
+
renderBarFrame,
|
|
22
|
+
uploadBarInstances,
|
|
23
|
+
rebuildGlyphBuffers,
|
|
24
|
+
rightAxisDataToPixel,
|
|
25
|
+
} from "./series-render";
|
|
26
|
+
|
|
27
|
+
const POINT_HIT_RADIUS_PX = 10;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Unified accessor for the currently hovered glyph. Returns either the
|
|
31
|
+
* real {@link SeriesChartRecord} from `_bars` (bar / stacked-area hits) or the
|
|
32
|
+
* synthetic one stored in `_hoveredSample` (line / scatter / non-stacked
|
|
33
|
+
* area hits), or `null`.
|
|
34
|
+
*/
|
|
35
|
+
export function getHoveredBar(chart: SeriesChart): SeriesChartRecord | null {
|
|
36
|
+
if (chart._hoveredBarIdx >= 0) {
|
|
37
|
+
return readBarRecord(
|
|
38
|
+
chart._bars,
|
|
39
|
+
chart._hoveredBarIdx,
|
|
40
|
+
chart._splitPrefixes.length,
|
|
41
|
+
chart._samples,
|
|
42
|
+
chart._series.length,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return chart._hoveredSample;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Handle mouse-move across all glyph types. Tests (in reverse paint order
|
|
51
|
+
* so top glyphs win): scatter points → line points → bars → areas.
|
|
52
|
+
* Updates `_hoveredBarIdx` or `_hoveredSample` and re-renders on change.
|
|
53
|
+
*/
|
|
54
|
+
export function handleBarHover(
|
|
55
|
+
chart: SeriesChart,
|
|
56
|
+
mx: number,
|
|
57
|
+
my: number,
|
|
58
|
+
): void {
|
|
59
|
+
if (!chart._lastLayout) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const layout = chart._lastLayout;
|
|
64
|
+
const plot = layout.plotRect;
|
|
65
|
+
|
|
66
|
+
if (
|
|
67
|
+
mx < plot.x ||
|
|
68
|
+
mx > plot.x + plot.width ||
|
|
69
|
+
my < plot.y ||
|
|
70
|
+
my > plot.y + plot.height
|
|
71
|
+
) {
|
|
72
|
+
clearHover(chart);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Convert mouse pixels to *logical* (category, value) coordinates.
|
|
77
|
+
// In horizontal mode the plot's X-axis is numeric and Y-axis is the
|
|
78
|
+
// flipped category index, so the raw pixel→data inversion differs.
|
|
79
|
+
const padXMin = layout.paddedXMin;
|
|
80
|
+
const padXMax = layout.paddedXMax;
|
|
81
|
+
const padYMin = layout.paddedYMin;
|
|
82
|
+
const padYMax = layout.paddedYMax;
|
|
83
|
+
let dataX: number;
|
|
84
|
+
let dataYLeft: number;
|
|
85
|
+
let pxPerDataX: number;
|
|
86
|
+
let pxPerDataYLeft: number;
|
|
87
|
+
if (chart._isHorizontal) {
|
|
88
|
+
// paddedY is flipped (catMax, catMin); undo that when inverting so
|
|
89
|
+
// dataYLeft (= logical category axis) grows from top to bottom.
|
|
90
|
+
const valMin = padXMin;
|
|
91
|
+
const valMax = padXMax;
|
|
92
|
+
const catTop = Math.min(padYMin, padYMax);
|
|
93
|
+
const catBot = Math.max(padYMin, padYMax);
|
|
94
|
+
const valAtMouse =
|
|
95
|
+
valMin + ((mx - plot.x) / plot.width) * (valMax - valMin);
|
|
96
|
+
const catAtMouse =
|
|
97
|
+
catTop + ((my - plot.y) / plot.height) * (catBot - catTop);
|
|
98
|
+
dataX = catAtMouse; // logical category → "dataX" in hit-test
|
|
99
|
+
dataYLeft = valAtMouse; // logical value → "dataYLeft" in hit-test
|
|
100
|
+
pxPerDataX = plot.height / (catBot - catTop);
|
|
101
|
+
pxPerDataYLeft = plot.width / (valMax - valMin);
|
|
102
|
+
} else {
|
|
103
|
+
dataX = padXMin + ((mx - plot.x) / plot.width) * (padXMax - padXMin);
|
|
104
|
+
dataYLeft =
|
|
105
|
+
padYMax - ((my - plot.y) / plot.height) * (padYMax - padYMin);
|
|
106
|
+
pxPerDataX = plot.width / (padXMax - padXMin);
|
|
107
|
+
pxPerDataYLeft = plot.height / (padYMax - padYMin);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const dataYRight =
|
|
111
|
+
chart._hasRightAxis && chart._rightDomain && !chart._isHorizontal
|
|
112
|
+
? chart._rightDomain.max -
|
|
113
|
+
((my - plot.y) / plot.height) *
|
|
114
|
+
(chart._rightDomain.max - chart._rightDomain.min)
|
|
115
|
+
: dataYLeft;
|
|
116
|
+
const pxPerDataYRight =
|
|
117
|
+
chart._hasRightAxis && chart._rightDomain && !chart._isHorizontal
|
|
118
|
+
? plot.height / (chart._rightDomain.max - chart._rightDomain.min)
|
|
119
|
+
: pxPerDataYLeft;
|
|
120
|
+
|
|
121
|
+
let nextBarIdx = -1;
|
|
122
|
+
let nextSample: SeriesChartRecord | null = null;
|
|
123
|
+
|
|
124
|
+
// 1. Scatter (top).
|
|
125
|
+
nextSample = hitTestPoints(
|
|
126
|
+
chart,
|
|
127
|
+
"scatter",
|
|
128
|
+
dataX,
|
|
129
|
+
dataYLeft,
|
|
130
|
+
dataYRight,
|
|
131
|
+
pxPerDataX,
|
|
132
|
+
pxPerDataYLeft,
|
|
133
|
+
pxPerDataYRight,
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
// 2. Line points (still above bars; treat as point hits).
|
|
137
|
+
if (!nextSample) {
|
|
138
|
+
nextSample = hitTestPoints(
|
|
139
|
+
chart,
|
|
140
|
+
"line",
|
|
141
|
+
dataX,
|
|
142
|
+
dataYLeft,
|
|
143
|
+
dataYRight,
|
|
144
|
+
pxPerDataX,
|
|
145
|
+
pxPerDataYLeft,
|
|
146
|
+
pxPerDataYRight,
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// 3. Bars (rect intersect).
|
|
151
|
+
if (!nextSample) {
|
|
152
|
+
const bars = chart._bars;
|
|
153
|
+
const ct = bars.chartType;
|
|
154
|
+
const sid = bars.seriesId;
|
|
155
|
+
const xC = bars.xCenter;
|
|
156
|
+
const hw = bars.halfWidth;
|
|
157
|
+
const by0 = bars.y0;
|
|
158
|
+
const by1 = bars.y1;
|
|
159
|
+
const ax = bars.axis;
|
|
160
|
+
const hidden = chart._hiddenSeries;
|
|
161
|
+
for (let i = 0; i < bars.count; i++) {
|
|
162
|
+
if (ct[i] !== BAR_TYPE_BAR) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (hidden.has(sid[i])) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const xc = xC[i];
|
|
171
|
+
const halfW = hw[i];
|
|
172
|
+
if (dataX < xc - halfW || dataX > xc + halfW) {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const dy = ax[i] === 0 ? dataYLeft : dataYRight;
|
|
177
|
+
const y0 = by0[i];
|
|
178
|
+
const y1 = by1[i];
|
|
179
|
+
const lo = y0 < y1 ? y0 : y1;
|
|
180
|
+
const hi = y0 < y1 ? y1 : y0;
|
|
181
|
+
if (dy >= lo && dy <= hi) {
|
|
182
|
+
nextBarIdx = i;
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// 4. Areas (strip hit — stacked records via `_bars`, unstacked via samples).
|
|
189
|
+
if (nextBarIdx < 0 && !nextSample) {
|
|
190
|
+
const areaHit = hitTestAreas(chart, dataX, dataYLeft, dataYRight);
|
|
191
|
+
if (areaHit) {
|
|
192
|
+
if (areaHit.idx >= 0) {
|
|
193
|
+
nextBarIdx = areaHit.idx;
|
|
194
|
+
} else {
|
|
195
|
+
nextSample = areaHit.bar;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
applyHover(chart, nextBarIdx, nextSample);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function hitTestPoints(
|
|
204
|
+
chart: SeriesChart,
|
|
205
|
+
chartType: "scatter" | "line",
|
|
206
|
+
dataX: number,
|
|
207
|
+
dataYLeft: number,
|
|
208
|
+
dataYRight: number,
|
|
209
|
+
pxPerDataX: number,
|
|
210
|
+
pxPerDataYLeft: number,
|
|
211
|
+
pxPerDataYRight: number,
|
|
212
|
+
): SeriesChartRecord | null {
|
|
213
|
+
const N = chart._numCategories;
|
|
214
|
+
const S = chart._series.length;
|
|
215
|
+
if (N === 0 || S === 0) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const samples = chart._samples;
|
|
220
|
+
const valid = chart._sampleValid;
|
|
221
|
+
|
|
222
|
+
const rSq = POINT_HIT_RADIUS_PX * POINT_HIT_RADIUS_PX;
|
|
223
|
+
let bestDistSq = rSq;
|
|
224
|
+
let best: SeriesChartRecord | null = null;
|
|
225
|
+
|
|
226
|
+
const positions = chart._categoryPositions;
|
|
227
|
+
for (const s of chart._series) {
|
|
228
|
+
if (s.chartType !== chartType) {
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (chart._hiddenSeries.has(s.seriesId)) {
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const dataY = s.axis === 1 ? dataYRight : dataYLeft;
|
|
237
|
+
const pyPerData = s.axis === 1 ? pxPerDataYRight : pxPerDataYLeft;
|
|
238
|
+
|
|
239
|
+
// In numeric mode the per-category X positions aren't dense so
|
|
240
|
+
// the catIdx-based narrowing doesn't apply — fall back to a
|
|
241
|
+
// full sweep. In category mode, narrow to ±radius around dataX.
|
|
242
|
+
const catMin = positions
|
|
243
|
+
? 0
|
|
244
|
+
: Math.max(0, Math.floor(dataX - POINT_HIT_RADIUS_PX / pxPerDataX));
|
|
245
|
+
const catMax = positions
|
|
246
|
+
? N - 1
|
|
247
|
+
: Math.min(
|
|
248
|
+
N - 1,
|
|
249
|
+
Math.ceil(dataX + POINT_HIT_RADIUS_PX / pxPerDataX),
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
for (let c = catMin; c <= catMax; c++) {
|
|
253
|
+
const idx = c * S + s.seriesId;
|
|
254
|
+
if (!((valid[idx >> 3] >> (idx & 7)) & 1)) {
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const v = samples[idx];
|
|
259
|
+
const x = positions ? positions[c] : c;
|
|
260
|
+
const dx = (x - dataX) * pxPerDataX;
|
|
261
|
+
const dy = (v - dataY) * pyPerData;
|
|
262
|
+
const distSq = dx * dx + dy * dy;
|
|
263
|
+
if (distSq < bestDistSq) {
|
|
264
|
+
bestDistSq = distSq;
|
|
265
|
+
best = {
|
|
266
|
+
catIdx: c,
|
|
267
|
+
aggIdx: s.aggIdx,
|
|
268
|
+
splitIdx: s.splitIdx,
|
|
269
|
+
seriesId: s.seriesId,
|
|
270
|
+
xCenter: x,
|
|
271
|
+
halfWidth: 0,
|
|
272
|
+
y0: 0,
|
|
273
|
+
y1: v,
|
|
274
|
+
value: v,
|
|
275
|
+
axis: s.axis,
|
|
276
|
+
|
|
277
|
+
// Tag as bar so the tooltip renderer treats it like one.
|
|
278
|
+
chartType: "bar",
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return best;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function hitTestAreas(
|
|
288
|
+
chart: SeriesChart,
|
|
289
|
+
dataX: number,
|
|
290
|
+
dataYLeft: number,
|
|
291
|
+
dataYRight: number,
|
|
292
|
+
): { idx: number; bar: SeriesChartRecord | null } | null {
|
|
293
|
+
// Closest category to the mouse; an area covers every [cat - 0.5, cat + 0.5]
|
|
294
|
+
// slot, so use `round(dataX)` as the candidate index.
|
|
295
|
+
const cat = Math.round(dataX);
|
|
296
|
+
if (cat < 0 || cat >= chart._numCategories) {
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (Math.abs(dataX - cat) > 0.5) {
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const S = chart._series.length;
|
|
305
|
+
const samples = chart._samples;
|
|
306
|
+
const valid = chart._sampleValid;
|
|
307
|
+
|
|
308
|
+
// Prefer stacked hits (iterate existing bar records — they carry y0/y1).
|
|
309
|
+
const bars = chart._bars;
|
|
310
|
+
const ct = bars.chartType;
|
|
311
|
+
const ci = bars.catIdx;
|
|
312
|
+
const sid = bars.seriesId;
|
|
313
|
+
const ax = bars.axis;
|
|
314
|
+
const by0 = bars.y0;
|
|
315
|
+
const by1 = bars.y1;
|
|
316
|
+
for (let i = 0; i < bars.count; i++) {
|
|
317
|
+
if (ct[i] !== BAR_TYPE_AREA) {
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (ci[i] !== cat) {
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (chart._hiddenSeries.has(sid[i])) {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const dy = ax[i] === 0 ? dataYLeft : dataYRight;
|
|
330
|
+
const y0 = by0[i];
|
|
331
|
+
const y1 = by1[i];
|
|
332
|
+
const lo = y0 < y1 ? y0 : y1;
|
|
333
|
+
const hi = y0 < y1 ? y1 : y0;
|
|
334
|
+
if (dy >= lo && dy <= hi) {
|
|
335
|
+
return { idx: i, bar: null };
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Unstacked area series: synthesise from samples.
|
|
340
|
+
for (const s of chart._series) {
|
|
341
|
+
if (s.chartType !== "area" || s.stack) {
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (chart._hiddenSeries.has(s.seriesId)) {
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const idx = cat * S + s.seriesId;
|
|
350
|
+
if (!((valid[idx >> 3] >> (idx & 7)) & 1)) {
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const v = samples[idx];
|
|
355
|
+
const dy = s.axis === 1 ? dataYRight : dataYLeft;
|
|
356
|
+
const lo = Math.min(0, v);
|
|
357
|
+
const hi = Math.max(0, v);
|
|
358
|
+
if (dy >= lo && dy <= hi) {
|
|
359
|
+
return {
|
|
360
|
+
idx: -1,
|
|
361
|
+
bar: {
|
|
362
|
+
catIdx: cat,
|
|
363
|
+
aggIdx: s.aggIdx,
|
|
364
|
+
splitIdx: s.splitIdx,
|
|
365
|
+
seriesId: s.seriesId,
|
|
366
|
+
xCenter: cat,
|
|
367
|
+
halfWidth: 0.5,
|
|
368
|
+
y0: 0,
|
|
369
|
+
y1: v,
|
|
370
|
+
value: v,
|
|
371
|
+
axis: s.axis,
|
|
372
|
+
chartType: "area",
|
|
373
|
+
},
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function clearHover(chart: SeriesChart): void {
|
|
382
|
+
if (chart._hoveredBarIdx !== -1 || chart._hoveredSample !== null) {
|
|
383
|
+
chart._hoveredBarIdx = -1;
|
|
384
|
+
chart._hoveredSample = null;
|
|
385
|
+
if (chart._glManager) {
|
|
386
|
+
renderBarFrame(chart, chart._glManager);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function applyHover(
|
|
392
|
+
chart: SeriesChart,
|
|
393
|
+
nextBarIdx: number,
|
|
394
|
+
nextSample: SeriesChartRecord | null,
|
|
395
|
+
): void {
|
|
396
|
+
const sameBar = chart._hoveredBarIdx === nextBarIdx;
|
|
397
|
+
const sameSample =
|
|
398
|
+
(chart._hoveredSample?.seriesId ?? -1) ===
|
|
399
|
+
(nextSample?.seriesId ?? -1) &&
|
|
400
|
+
(chart._hoveredSample?.catIdx ?? -1) === (nextSample?.catIdx ?? -1);
|
|
401
|
+
if (sameBar && sameSample) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
chart._hoveredBarIdx = nextBarIdx;
|
|
406
|
+
chart._hoveredSample = nextSample;
|
|
407
|
+
if (chart._glManager) {
|
|
408
|
+
renderBarFrame(chart, chart._glManager);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Handle a click on the legend area. Returns true when the click hit a
|
|
414
|
+
* legend entry (the caller should then treat the event as consumed).
|
|
415
|
+
*/
|
|
416
|
+
export function handleBarLegendClick(
|
|
417
|
+
chart: SeriesChart,
|
|
418
|
+
mx: number,
|
|
419
|
+
my: number,
|
|
420
|
+
): boolean {
|
|
421
|
+
if (chart._legendRects.length === 0) {
|
|
422
|
+
return false;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
for (const entry of chart._legendRects) {
|
|
426
|
+
const r = entry.rect;
|
|
427
|
+
if (
|
|
428
|
+
mx >= r.x &&
|
|
429
|
+
mx <= r.x + r.width &&
|
|
430
|
+
my >= r.y &&
|
|
431
|
+
my <= r.y + r.height
|
|
432
|
+
) {
|
|
433
|
+
if (chart._hiddenSeries.has(entry.seriesId)) {
|
|
434
|
+
chart._hiddenSeries.delete(entry.seriesId);
|
|
435
|
+
} else {
|
|
436
|
+
chart._hiddenSeries.add(entry.seriesId);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// Hidden-series change affects which bars contribute to
|
|
440
|
+
// the auto-fit extent and which scatter / line points are
|
|
441
|
+
// uploaded. Bars rebuild via `uploadBarInstances` (it
|
|
442
|
+
// filters hidden). Scatter and line rebuild because their
|
|
443
|
+
// bulk-packed per-axis buffers need to drop hidden points
|
|
444
|
+
// — the line glyph used to skip rebuilds (per-series
|
|
445
|
+
// buffers + draw-path filter), but with the bulk pack the
|
|
446
|
+
// hidden filter must apply at upload time. Area still
|
|
447
|
+
// uses per-series buffers; its draw path skips hidden.
|
|
448
|
+
// The per-category extent buckets (`_catExtents`) are
|
|
449
|
+
// also invalidated — they hold a pointer to the hidden
|
|
450
|
+
// set used at build time and rebuild on next read.
|
|
451
|
+
chart._autoFitCache = null;
|
|
452
|
+
chart._legendCacheValid = false;
|
|
453
|
+
chart._catExtentsHidden = null;
|
|
454
|
+
if (chart._glManager) {
|
|
455
|
+
uploadBarInstances(chart, chart._glManager);
|
|
456
|
+
rebuildGlyphBuffers(chart, chart._glManager);
|
|
457
|
+
renderBarFrame(chart, chart._glManager);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return true;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
return false;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Build the per-bar tooltip content lines.
|
|
469
|
+
*/
|
|
470
|
+
export function buildBarTooltipLines(
|
|
471
|
+
chart: SeriesChart,
|
|
472
|
+
b: SeriesChartRecord,
|
|
473
|
+
): string[] {
|
|
474
|
+
const lines: string[] = [];
|
|
475
|
+
const s = chart._series[b.seriesId];
|
|
476
|
+
const categoryPath = formatBarCategoryPath(chart, b.catIdx);
|
|
477
|
+
if (categoryPath) {
|
|
478
|
+
lines.push(categoryPath);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const yFmt = chart.getColumnFormatter(s.aggName, "value");
|
|
482
|
+
lines.push(`${s.aggName}: ${yFmt(b.value)}`);
|
|
483
|
+
if (s.splitKey) {
|
|
484
|
+
lines.push(`Split: ${s.splitKey}`);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (b.y0 !== 0) {
|
|
488
|
+
lines.push(`Base: ${yFmt(b.y0)}`);
|
|
489
|
+
lines.push(`Top: ${yFmt(b.y1)}`);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
return lines;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Format the hierarchical path label for a given category index. Used by
|
|
497
|
+
* the tooltip — the axis uses per-level text directly instead.
|
|
498
|
+
*/
|
|
499
|
+
export function formatBarCategoryPath(
|
|
500
|
+
chart: SeriesChart,
|
|
501
|
+
catIdx: number,
|
|
502
|
+
): string {
|
|
503
|
+
// Numeric category mode: resolve from the bar's xCenter (real data
|
|
504
|
+
// value) rather than the row-path label array, which is empty when
|
|
505
|
+
// the single group_by level is non-string.
|
|
506
|
+
if (chart._categoryAxisMode === "numeric" && chart._numericCategoryDomain) {
|
|
507
|
+
const bars = chart._bars;
|
|
508
|
+
let v: number | null = null;
|
|
509
|
+
for (let i = 0; i < bars.count; i++) {
|
|
510
|
+
if (bars.catIdx[i] === catIdx) {
|
|
511
|
+
v = bars.xCenter[i];
|
|
512
|
+
break;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (v == null) {
|
|
517
|
+
return "";
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
const xColumn = chart._groupBy[0];
|
|
521
|
+
return chart.getColumnFormatter(xColumn, "value")(v);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
if (chart._rowPaths.length === 0) {
|
|
525
|
+
return "";
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const parts: string[] = [];
|
|
529
|
+
for (const rp of chart._rowPaths) {
|
|
530
|
+
const s = rp.labels[catIdx];
|
|
531
|
+
if (s != null && s !== "") {
|
|
532
|
+
parts.push(s);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
return parts.join(" / ");
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
export function showBarPinnedTooltip(chart: SeriesChart, barIdx: number): void {
|
|
540
|
+
if (barIdx < 0 || barIdx >= chart._bars.count) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
chart._pinnedBarIdx = barIdx;
|
|
545
|
+
pinTooltip(
|
|
546
|
+
chart,
|
|
547
|
+
readBarRecord(
|
|
548
|
+
chart._bars,
|
|
549
|
+
barIdx,
|
|
550
|
+
chart._splitPrefixes.length,
|
|
551
|
+
chart._samples,
|
|
552
|
+
chart._series.length,
|
|
553
|
+
),
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Pin a tooltip against a synthetic BarRecord (scatter/line/area hit).
|
|
559
|
+
*/
|
|
560
|
+
export function showBarPinnedTooltipForSample(
|
|
561
|
+
chart: SeriesChart,
|
|
562
|
+
bar: SeriesChartRecord,
|
|
563
|
+
): void {
|
|
564
|
+
chart._pinnedBarIdx = -1;
|
|
565
|
+
pinTooltip(chart, bar);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
function pinTooltip(chart: SeriesChart, b: SeriesChartRecord): void {
|
|
569
|
+
chart._tooltip.dismiss();
|
|
570
|
+
if (!chart._lastLayout) {
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
const layout = chart._lastLayout;
|
|
575
|
+
|
|
576
|
+
// Anchor at the bar midpoint for bar glyphs (tooltip reads against
|
|
577
|
+
// the body); at the point itself (`y1`) for line / scatter / area.
|
|
578
|
+
const glyph = chart._series[b.seriesId]?.chartType ?? "bar";
|
|
579
|
+
const anchorV = glyph === "bar" ? (b.y0 + b.y1) / 2 : b.y1;
|
|
580
|
+
const pos =
|
|
581
|
+
b.axis === 0
|
|
582
|
+
? chart._isHorizontal
|
|
583
|
+
? layout.dataToPixel(anchorV, b.xCenter)
|
|
584
|
+
: layout.dataToPixel(b.xCenter, anchorV)
|
|
585
|
+
: rightAxisDataToPixel(chart, b.xCenter, anchorV);
|
|
586
|
+
|
|
587
|
+
const lines = buildBarTooltipLines(chart, b);
|
|
588
|
+
if (lines.length === 0) {
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
chart._tooltip.pin(lines, pos, layout);
|
|
593
|
+
|
|
594
|
+
chart._hoveredBarIdx = -1;
|
|
595
|
+
chart._hoveredSample = null;
|
|
596
|
+
if (chart._glManager) {
|
|
597
|
+
renderBarFrame(chart, chart._glManager);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
export function dismissBarPinnedTooltip(chart: SeriesChart): void {
|
|
602
|
+
chart._tooltip.dismiss();
|
|
603
|
+
chart._pinnedBarIdx = -1;
|
|
604
|
+
}
|