mirror of
https://github.com/grafana/grafana.git
synced 2025-01-02 04:07:15 -06:00
TimeSeries: Implement ad hoc y-zoom via Shift-drag (#75408)
This commit is contained in:
parent
bb9e66e671
commit
32ed3e8009
@ -1,10 +1,10 @@
|
||||
import { useLayoutEffect } from 'react';
|
||||
|
||||
import { UPlotConfigBuilder } from '../config/UPlotConfigBuilder';
|
||||
import { pluginLog } from '../utils';
|
||||
|
||||
interface ZoomPluginProps {
|
||||
onZoom: (range: { from: number; to: number }) => void;
|
||||
withZoomY?: boolean;
|
||||
config: UPlotConfigBuilder;
|
||||
}
|
||||
|
||||
@ -14,41 +14,86 @@ const MIN_ZOOM_DIST = 5;
|
||||
/**
|
||||
* @alpha
|
||||
*/
|
||||
export const ZoomPlugin = ({ onZoom, config }: ZoomPluginProps) => {
|
||||
export const ZoomPlugin = ({ onZoom, config, withZoomY = false }: ZoomPluginProps) => {
|
||||
useLayoutEffect(() => {
|
||||
config.addHook('setSelect', (u) => {
|
||||
const min = u.posToVal(u.select.left, 'x');
|
||||
const max = u.posToVal(u.select.left + u.select.width, 'x');
|
||||
let yZoomed = false;
|
||||
let yDrag = false;
|
||||
|
||||
if (u.select.width >= MIN_ZOOM_DIST) {
|
||||
pluginLog('ZoomPlugin', false, 'selected', {
|
||||
min,
|
||||
max,
|
||||
bbox: {
|
||||
left: u.bbox.left / window.devicePixelRatio + u.select.left,
|
||||
top: u.bbox.top / window.devicePixelRatio,
|
||||
height: u.bbox.height / window.devicePixelRatio,
|
||||
width: u.select.width,
|
||||
if (withZoomY) {
|
||||
config.addHook('init', (u) => {
|
||||
u.root!.addEventListener(
|
||||
'mousedown',
|
||||
(e) => {
|
||||
if (e.button === 0 && e.shiftKey) {
|
||||
yDrag = true;
|
||||
|
||||
u.cursor!.drag!.x = false;
|
||||
u.cursor!.drag!.y = true;
|
||||
|
||||
let onUp = (e: MouseEvent) => {
|
||||
u.cursor!.drag!.x = true;
|
||||
u.cursor!.drag!.y = false;
|
||||
document.removeEventListener('mouseup', onUp, true);
|
||||
};
|
||||
|
||||
document.addEventListener('mouseup', onUp, true);
|
||||
}
|
||||
},
|
||||
});
|
||||
onZoom({ from: min, to: max });
|
||||
true
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
config.addHook('setSelect', (u) => {
|
||||
if (withZoomY && yDrag) {
|
||||
if (u.select.height >= MIN_ZOOM_DIST) {
|
||||
for (let key in u.scales!) {
|
||||
if (key !== 'x') {
|
||||
const maxY = u.posToVal(u.select.top, key);
|
||||
const minY = u.posToVal(u.select.top + u.select.height, key);
|
||||
|
||||
u.setScale(key, { min: minY, max: maxY });
|
||||
}
|
||||
}
|
||||
|
||||
yZoomed = true;
|
||||
}
|
||||
|
||||
yDrag = false;
|
||||
} else {
|
||||
if (u.select.width >= MIN_ZOOM_DIST) {
|
||||
const minX = u.posToVal(u.select.left, 'x');
|
||||
const maxX = u.posToVal(u.select.left + u.select.width, 'x');
|
||||
|
||||
onZoom({ from: minX, to: maxX });
|
||||
}
|
||||
}
|
||||
|
||||
// manually hide selected region (since cursor.drag.setScale = false)
|
||||
/* @ts-ignore */
|
||||
u.setSelect({ left: 0, width: 0 }, false);
|
||||
u.setSelect({ left: 0, width: 0, top: 0, height: 0 }, false);
|
||||
});
|
||||
|
||||
config.setCursor({
|
||||
bind: {
|
||||
dblclick: (u) => () => {
|
||||
let xScale = u.scales.x;
|
||||
if (withZoomY && yZoomed) {
|
||||
for (let key in u.scales!) {
|
||||
if (key !== 'x') {
|
||||
// @ts-ignore (this is not typed correctly in uPlot, assigning nulls means auto-scale / reset)
|
||||
u.setScale(key, { min: null, max: null });
|
||||
}
|
||||
}
|
||||
|
||||
const frTs = xScale.min!;
|
||||
const toTs = xScale.max!;
|
||||
const pad = (toTs - frTs) / 2;
|
||||
yZoomed = false;
|
||||
} else {
|
||||
let xScale = u.scales.x;
|
||||
|
||||
onZoom({ from: frTs - pad, to: toTs + pad });
|
||||
const frTs = xScale.min!;
|
||||
const toTs = xScale.max!;
|
||||
const pad = (toTs - frTs) / 2;
|
||||
|
||||
onZoom({ from: frTs - pad, to: toTs + pad });
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
@ -254,7 +254,7 @@ export const CandlestickPanel = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<ZoomPlugin config={config} onZoom={onChangeTimeRange} />
|
||||
<ZoomPlugin config={config} onZoom={onChangeTimeRange} withZoomY={true} />
|
||||
<TooltipPlugin
|
||||
data={alignedDataFrame}
|
||||
config={config}
|
||||
|
@ -87,7 +87,7 @@ export const TimeSeriesPanel = ({
|
||||
return (
|
||||
<>
|
||||
<KeyboardPlugin config={config} />
|
||||
<ZoomPlugin config={config} onZoom={onChangeTimeRange} />
|
||||
<ZoomPlugin config={config} onZoom={onChangeTimeRange} withZoomY={true} />
|
||||
{options.tooltip.mode === TooltipDisplayMode.None || (
|
||||
<TooltipPlugin
|
||||
frames={frames}
|
||||
|
Loading…
Reference in New Issue
Block a user