mirror of
https://github.com/grafana/grafana.git
synced 2024-12-02 05:29:42 -06:00
Canvas: Add support for line animation (#85556)
This commit is contained in:
parent
8e8bfae761
commit
883a41e8aa
@ -5,6 +5,7 @@ import { PanelOptionsSupplier } from '@grafana/data/src/panel/PanelPlugin';
|
||||
import { ColorDimensionConfig, ScaleDimensionConfig } from '@grafana/schema';
|
||||
import { config } from 'app/core/config';
|
||||
|
||||
import { LineStyleConfig } from '../../plugins/panel/canvas/editor/LineStyleEditor';
|
||||
import { DimensionContext } from '../dimensions';
|
||||
|
||||
import { BackgroundConfig, Constraint, LineConfig, Placement, StandardEditorConfig } from './types';
|
||||
@ -56,7 +57,7 @@ export interface CanvasConnection {
|
||||
path: ConnectionPath;
|
||||
color?: ColorDimensionConfig;
|
||||
size?: ScaleDimensionConfig;
|
||||
lineStyle?: string;
|
||||
lineStyle?: LineStyleConfig;
|
||||
vertices?: ConnectionCoordinates[];
|
||||
radius?: ScaleDimensionConfig;
|
||||
direction?: ConnectionDirection;
|
||||
|
@ -144,12 +144,8 @@ export const ConnectionSVG = ({
|
||||
const xDist = x2 - x1;
|
||||
const yDist = y2 - y1;
|
||||
|
||||
const { strokeColor, strokeWidth, strokeRadius, arrowDirection, lineStyle } = getConnectionStyles(
|
||||
info,
|
||||
scene,
|
||||
defaultArrowSize,
|
||||
defaultArrowDirection
|
||||
);
|
||||
const { strokeColor, strokeWidth, strokeRadius, arrowDirection, lineStyle, shouldAnimate } =
|
||||
getConnectionStyles(info, scene, defaultArrowSize, defaultArrowDirection);
|
||||
|
||||
const isSelected = selectedConnection === v && scene.panel.context.instanceState.selectedConnection;
|
||||
|
||||
@ -345,6 +341,16 @@ export const ConnectionSVG = ({
|
||||
? `url(#${CONNECTION_HEAD_ID_END})`
|
||||
: undefined;
|
||||
|
||||
const getAnimationDirection = () => {
|
||||
let values = '100;0';
|
||||
|
||||
if (arrowDirection === ConnectionDirection.Reverse) {
|
||||
values = '0;100';
|
||||
}
|
||||
|
||||
return values;
|
||||
};
|
||||
|
||||
return (
|
||||
<svg className={styles.connection} key={idx}>
|
||||
<g onClick={() => selectConnection(v)}>
|
||||
@ -389,10 +395,22 @@ export const ConnectionSVG = ({
|
||||
stroke={strokeColor}
|
||||
strokeWidth={strokeWidth}
|
||||
strokeDasharray={lineStyle}
|
||||
strokeDashoffset={1}
|
||||
fill={'none'}
|
||||
markerEnd={markerEnd}
|
||||
markerStart={markerStart}
|
||||
/>
|
||||
>
|
||||
{shouldAnimate && (
|
||||
<animate
|
||||
attributeName="stroke-dashoffset"
|
||||
values={getAnimationDirection()}
|
||||
dur="5s"
|
||||
calcMode="linear"
|
||||
repeatCount="indefinite"
|
||||
fill={'freeze'}
|
||||
/>
|
||||
)}
|
||||
</path>
|
||||
{isSelected && (
|
||||
<g>
|
||||
{vertices.map((value, index) => {
|
||||
@ -455,12 +473,24 @@ export const ConnectionSVG = ({
|
||||
markerEnd={markerEnd}
|
||||
markerStart={markerStart}
|
||||
strokeDasharray={lineStyle}
|
||||
strokeDashoffset={1}
|
||||
x1={x1}
|
||||
y1={y1}
|
||||
x2={x2}
|
||||
y2={y2}
|
||||
cursor={connectionCursorStyle}
|
||||
/>
|
||||
>
|
||||
{shouldAnimate && (
|
||||
<animate
|
||||
attributeName="stroke-dashoffset"
|
||||
values={getAnimationDirection()}
|
||||
dur="5s"
|
||||
calcMode="linear"
|
||||
repeatCount="indefinite"
|
||||
fill={'freeze'}
|
||||
/>
|
||||
)}
|
||||
</line>
|
||||
{isSelected && (
|
||||
<circle
|
||||
id={CONNECTION_VERTEX_ADD_ID}
|
||||
|
@ -1,24 +1,63 @@
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import { SelectableValue, StandardEditorProps } from '@grafana/data';
|
||||
import { RadioButtonGroup } from '@grafana/ui/src';
|
||||
import { Field, RadioButtonGroup, Switch } from '@grafana/ui/src';
|
||||
|
||||
import { LineStyle } from '../types';
|
||||
|
||||
const options: Array<SelectableValue<LineStyle>> = [
|
||||
{ value: LineStyle.Solid, label: 'Solid' },
|
||||
{ value: LineStyle.Dashed, label: 'Dashed' },
|
||||
{ value: LineStyle.Dotted, label: 'Dotted' },
|
||||
];
|
||||
|
||||
export const LineStyleEditor = ({ value, onChange }: StandardEditorProps<string, undefined, undefined>) => {
|
||||
const lineStyle = value ?? LineStyle.Solid;
|
||||
export interface LineStyleConfig {
|
||||
style: LineStyle;
|
||||
animate?: boolean;
|
||||
}
|
||||
|
||||
type Props = StandardEditorProps<LineStyleConfig>;
|
||||
|
||||
export const defaultLineStyleConfig: LineStyleConfig = {
|
||||
style: LineStyle.Solid,
|
||||
animate: false,
|
||||
};
|
||||
|
||||
export const LineStyleEditor = ({ value, onChange }: Props) => {
|
||||
if (!value) {
|
||||
value = defaultLineStyleConfig;
|
||||
} else if (typeof value !== 'object') {
|
||||
value = {
|
||||
style: value,
|
||||
animate: false,
|
||||
};
|
||||
}
|
||||
|
||||
const onLineStyleChange = useCallback(
|
||||
(lineStyle: string) => {
|
||||
onChange(lineStyle);
|
||||
(lineStyle: LineStyle) => {
|
||||
onChange({ ...value, style: lineStyle });
|
||||
},
|
||||
[onChange]
|
||||
[onChange, value]
|
||||
);
|
||||
|
||||
return <RadioButtonGroup value={lineStyle} options={options} onChange={onLineStyleChange} fullWidth />;
|
||||
const onAnimateChange = useCallback(
|
||||
(animate: boolean) => {
|
||||
onChange({ ...value, animate });
|
||||
},
|
||||
[onChange, value]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<RadioButtonGroup value={value.style} options={options} onChange={onLineStyleChange} fullWidth />
|
||||
{value.style !== LineStyle.Solid && (
|
||||
<>
|
||||
<br />
|
||||
<Field label="Animate">
|
||||
<Switch value={value.animate} onChange={(e) => onAnimateChange(e.currentTarget.checked)} />
|
||||
</Field>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -47,9 +47,11 @@ export interface ConnectionState {
|
||||
export enum LineStyle {
|
||||
Solid = 'solid',
|
||||
Dashed = 'dashed',
|
||||
Dotted = 'dotted',
|
||||
}
|
||||
|
||||
export enum StrokeDasharray {
|
||||
Solid = '0',
|
||||
Dashed = '8 8',
|
||||
Dotted = '3',
|
||||
}
|
||||
|
@ -403,8 +403,21 @@ export const getConnectionStyles = (
|
||||
const strokeWidth = info.size ? scene.context.getScale(info.size).get(lastRowIndex) : defaultArrowSize;
|
||||
const strokeRadius = info.radius ? scene.context.getScale(info.radius).get(lastRowIndex) : 0;
|
||||
const arrowDirection = info.direction ? info.direction : defaultArrowDirection;
|
||||
const lineStyle = info.lineStyle === LineStyle.Dashed ? StrokeDasharray.Dashed : StrokeDasharray.Solid;
|
||||
return { strokeColor, strokeWidth, strokeRadius, arrowDirection, lineStyle };
|
||||
const lineStyle = getLineStyle(info.lineStyle?.style);
|
||||
const shouldAnimate = info.lineStyle?.animate;
|
||||
|
||||
return { strokeColor, strokeWidth, strokeRadius, arrowDirection, lineStyle, shouldAnimate };
|
||||
};
|
||||
|
||||
const getLineStyle = (lineStyle?: LineStyle) => {
|
||||
switch (lineStyle) {
|
||||
case LineStyle.Dashed:
|
||||
return StrokeDasharray.Dashed;
|
||||
case LineStyle.Dotted:
|
||||
return StrokeDasharray.Dotted;
|
||||
default:
|
||||
return StrokeDasharray.Solid;
|
||||
}
|
||||
};
|
||||
|
||||
export const getParentBoundingClientRect = (scene: Scene) => {
|
||||
|
Loading…
Reference in New Issue
Block a user