BarChart: fix hovered series highlight in tooltip (#44882)

pull/46191/head
Leon Sorokin 3 years ago committed by GitHub
parent b1125c0ba3
commit 3e3a657343
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 56
      public/app/plugins/panel/barchart/__snapshots__/utils.test.ts.snap
  2. 86
      public/app/plugins/panel/barchart/bars.ts

@ -59,15 +59,18 @@ Object {
}, },
], ],
"cursor": Object { "cursor": Object {
"dataIdx": [Function],
"drag": Object { "drag": Object {
"setScale": false, "setScale": false,
"x": false,
"y": false,
}, },
"focus": Object { "focus": Object {
"prox": 30, "prox": 30,
}, },
"points": Object { "points": Object {
"fill": [Function], "bbox": [Function],
"show": false, "fill": "rgba(255,255,255,0.4)",
"size": [Function], "size": [Function],
"stroke": [Function], "stroke": [Function],
"width": [Function], "width": [Function],
@ -195,15 +198,18 @@ Object {
}, },
], ],
"cursor": Object { "cursor": Object {
"dataIdx": [Function],
"drag": Object { "drag": Object {
"setScale": false, "setScale": false,
"x": false,
"y": false,
}, },
"focus": Object { "focus": Object {
"prox": 30, "prox": 30,
}, },
"points": Object { "points": Object {
"fill": [Function], "bbox": [Function],
"show": false, "fill": "rgba(255,255,255,0.4)",
"size": [Function], "size": [Function],
"stroke": [Function], "stroke": [Function],
"width": [Function], "width": [Function],
@ -331,15 +337,18 @@ Object {
}, },
], ],
"cursor": Object { "cursor": Object {
"dataIdx": [Function],
"drag": Object { "drag": Object {
"setScale": false, "setScale": false,
"x": false,
"y": false,
}, },
"focus": Object { "focus": Object {
"prox": 30, "prox": 30,
}, },
"points": Object { "points": Object {
"fill": [Function], "bbox": [Function],
"show": false, "fill": "rgba(255,255,255,0.4)",
"size": [Function], "size": [Function],
"stroke": [Function], "stroke": [Function],
"width": [Function], "width": [Function],
@ -467,15 +476,18 @@ Object {
}, },
], ],
"cursor": Object { "cursor": Object {
"dataIdx": [Function],
"drag": Object { "drag": Object {
"setScale": false, "setScale": false,
"x": false,
"y": false,
}, },
"focus": Object { "focus": Object {
"prox": 30, "prox": 30,
}, },
"points": Object { "points": Object {
"fill": [Function], "bbox": [Function],
"show": false, "fill": "rgba(255,255,255,0.4)",
"size": [Function], "size": [Function],
"stroke": [Function], "stroke": [Function],
"width": [Function], "width": [Function],
@ -603,15 +615,18 @@ Object {
}, },
], ],
"cursor": Object { "cursor": Object {
"dataIdx": [Function],
"drag": Object { "drag": Object {
"setScale": false, "setScale": false,
"x": false,
"y": false,
}, },
"focus": Object { "focus": Object {
"prox": 30, "prox": 30,
}, },
"points": Object { "points": Object {
"fill": [Function], "bbox": [Function],
"show": false, "fill": "rgba(255,255,255,0.4)",
"size": [Function], "size": [Function],
"stroke": [Function], "stroke": [Function],
"width": [Function], "width": [Function],
@ -739,15 +754,18 @@ Object {
}, },
], ],
"cursor": Object { "cursor": Object {
"dataIdx": [Function],
"drag": Object { "drag": Object {
"setScale": false, "setScale": false,
"x": false,
"y": false,
}, },
"focus": Object { "focus": Object {
"prox": 30, "prox": 30,
}, },
"points": Object { "points": Object {
"fill": [Function], "bbox": [Function],
"show": false, "fill": "rgba(255,255,255,0.4)",
"size": [Function], "size": [Function],
"stroke": [Function], "stroke": [Function],
"width": [Function], "width": [Function],
@ -875,15 +893,18 @@ Object {
}, },
], ],
"cursor": Object { "cursor": Object {
"dataIdx": [Function],
"drag": Object { "drag": Object {
"setScale": false, "setScale": false,
"x": false,
"y": false,
}, },
"focus": Object { "focus": Object {
"prox": 30, "prox": 30,
}, },
"points": Object { "points": Object {
"fill": [Function], "bbox": [Function],
"show": false, "fill": "rgba(255,255,255,0.4)",
"size": [Function], "size": [Function],
"stroke": [Function], "stroke": [Function],
"width": [Function], "width": [Function],
@ -1011,15 +1032,18 @@ Object {
}, },
], ],
"cursor": Object { "cursor": Object {
"dataIdx": [Function],
"drag": Object { "drag": Object {
"setScale": false, "setScale": false,
"x": false,
"y": false,
}, },
"focus": Object { "focus": Object {
"prox": 30, "prox": 30,
}, },
"points": Object { "points": Object {
"fill": [Function], "bbox": [Function],
"show": false, "fill": "rgba(255,255,255,0.4)",
"size": [Function], "size": [Function],
"stroke": [Function], "stroke": [Function],
"width": [Function], "width": [Function],

@ -125,12 +125,7 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
} }
let qt: Quadtree; let qt: Quadtree;
let hovered: Rect | undefined = undefined; let hRect: Rect | null;
let barMark = document.createElement('div');
barMark.classList.add('bar-mark');
barMark.style.position = 'absolute';
barMark.style.background = 'rgba(255,255,255,0.4)';
const xSplits: Axis.Splits = (u: uPlot) => { const xSplits: Axis.Splits = (u: uPlot) => {
const dim = isXHorizontal ? u.bbox.width : u.bbox.height; const dim = isXHorizontal ? u.bbox.width : u.bbox.height;
@ -408,7 +403,47 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
const init = (u: uPlot) => { const init = (u: uPlot) => {
let over = u.over; let over = u.over;
over.style.overflow = 'hidden'; over.style.overflow = 'hidden';
over.appendChild(barMark); u.root.querySelectorAll('.u-cursor-pt').forEach((el) => {
(el as HTMLElement).style.borderRadius = '0';
});
};
const cursor: uPlot.Cursor = {
x: false,
y: false,
drag: {
x: false,
y: false,
},
dataIdx: (u, seriesIdx) => {
if (seriesIdx === 1) {
hRect = null;
let cx = u.cursor.left! * devicePixelRatio;
let cy = u.cursor.top! * devicePixelRatio;
qt.get(cx, cy, 1, 1, (o) => {
if (pointWithin(cx, cy, o.x, o.y, o.x + o.w, o.y + o.h)) {
hRect = o;
}
});
}
return hRect && seriesIdx === hRect.sidx ? hRect.didx : null;
},
points: {
fill: 'rgba(255,255,255,0.4)',
bbox: (u, seriesIdx) => {
let isHovered = hRect && seriesIdx === hRect.sidx;
return {
left: isHovered ? hRect!.x / devicePixelRatio : -10,
top: isHovered ? hRect!.y / devicePixelRatio : -10,
width: isHovered ? hRect!.w / devicePixelRatio : 0,
height: isHovered ? hRect!.h / devicePixelRatio : 0,
};
},
},
}; };
// Build bars // Build bars
@ -518,35 +553,10 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
updateTooltipPosition, updateTooltipPosition,
u u
) => { ) => {
let found: Rect | undefined; if (hRect) {
let cx = u.cursor.left! * devicePixelRatio; updateActiveSeriesIdx(hRect.sidx);
let cy = u.cursor.top! * devicePixelRatio; updateActiveDatapointIdx(hRect.didx);
qt.get(cx, cy, 1, 1, (o) => {
if (pointWithin(cx, cy, o.x, o.y, o.x + o.w, o.y + o.h)) {
found = o;
}
});
if (found) {
// prettier-ignore
if (found !== hovered) {
barMark.style.display = '';
barMark.style.left = found.x / devicePixelRatio + 'px';
barMark.style.top = found.y / devicePixelRatio + 'px';
barMark.style.width = found.w / devicePixelRatio + 'px';
barMark.style.height = found.h / devicePixelRatio + 'px';
hovered = found;
updateActiveSeriesIdx(hovered.sidx);
updateActiveDatapointIdx(hovered.didx);
updateTooltipPosition(); updateTooltipPosition();
}
} else if (hovered !== undefined) {
updateActiveSeriesIdx(hovered!.sidx);
updateActiveDatapointIdx(hovered!.didx);
updateTooltipPosition();
hovered = undefined;
barMark.style.display = 'none';
} else { } else {
updateTooltipPosition(true); updateTooltipPosition(true);
} }
@ -567,11 +577,7 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
} }
return { return {
cursor: { cursor,
x: false,
y: false,
points: { show: false },
},
// scale & axis opts // scale & axis opts
xRange, xRange,
xValues, xValues,

Loading…
Cancel
Save