mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Canvas: Improve anchor UX (#62409)
Co-authored-by: nmarrs <nathanielmarrs@gmail.com>
This commit is contained in:
parent
43ce077133
commit
bbb572e73f
@ -14,6 +14,9 @@ type Props = {
|
||||
|
||||
export const CONNECTION_ANCHOR_DIV_ID = 'connectionControl';
|
||||
export const CONNECTION_ANCHOR_ALT = 'connection anchor';
|
||||
export const CONNECTION_ANCHOR_HIGHLIGHT_OFFSET = 8;
|
||||
|
||||
const ANCHOR_PADDING = 3;
|
||||
|
||||
export const ConnectionAnchors = ({ setRef, handleMouseLeave }: Props) => {
|
||||
const highlightEllipseRef = useRef<HTMLDivElement>(null);
|
||||
@ -30,8 +33,8 @@ export const ConnectionAnchors = ({ setRef, handleMouseLeave }: Props) => {
|
||||
|
||||
if (highlightEllipseRef.current && event.target.style) {
|
||||
highlightEllipseRef.current.style.display = 'block';
|
||||
highlightEllipseRef.current.style.top = `calc(${event.target.style.top} - ${halfSizeHighlightEllipse}px)`;
|
||||
highlightEllipseRef.current.style.left = `calc(${event.target.style.left} - ${halfSizeHighlightEllipse}px)`;
|
||||
highlightEllipseRef.current.style.top = `calc(${event.target.style.top} - ${halfSizeHighlightEllipse}px + ${ANCHOR_PADDING}px)`;
|
||||
highlightEllipseRef.current.style.left = `calc(${event.target.style.left} - ${halfSizeHighlightEllipse}px + ${ANCHOR_PADDING}px)`;
|
||||
}
|
||||
};
|
||||
|
||||
@ -78,8 +81,8 @@ export const ConnectionAnchors = ({ setRef, handleMouseLeave }: Props) => {
|
||||
|
||||
// Convert anchor coords to relative percentage
|
||||
const style = {
|
||||
top: `calc(${-anchor.y * 50 + 50}% - ${halfSize}px)`,
|
||||
left: `calc(${anchor.x * 50 + 50}% - ${halfSize}px)`,
|
||||
top: `calc(${-anchor.y * 50 + 50}% - ${halfSize}px - ${ANCHOR_PADDING}px)`,
|
||||
left: `calc(${anchor.x * 50 + 50}% - ${halfSize}px - ${ANCHOR_PADDING}px)`,
|
||||
};
|
||||
|
||||
return (
|
||||
@ -122,10 +125,11 @@ const getStyles = (theme: GrafanaTheme2) => ({
|
||||
height: calc(100% + 60px);
|
||||
`,
|
||||
anchor: css`
|
||||
padding: ${ANCHOR_PADDING}px;
|
||||
position: absolute;
|
||||
cursor: cursor;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
width: calc(5px + 2 * ${ANCHOR_PADDING}px);
|
||||
height: calc(5px + 2 * ${ANCHOR_PADDING}px);
|
||||
z-index: 100;
|
||||
pointer-events: auto !important;
|
||||
`,
|
||||
|
@ -4,7 +4,7 @@ import { ConnectionPath } from 'app/features/canvas';
|
||||
import { ElementState } from 'app/features/canvas/runtime/element';
|
||||
import { Scene } from 'app/features/canvas/runtime/scene';
|
||||
|
||||
import { CONNECTION_ANCHOR_ALT, ConnectionAnchors } from './ConnectionAnchors';
|
||||
import { CONNECTION_ANCHOR_ALT, ConnectionAnchors, CONNECTION_ANCHOR_HIGHLIGHT_OFFSET } from './ConnectionAnchors';
|
||||
import { ConnectionSVG } from './ConnectionSVG';
|
||||
import { isConnectionSource, isConnectionTarget } from './utils';
|
||||
|
||||
@ -16,6 +16,7 @@ export class Connections {
|
||||
connectionSource?: ElementState;
|
||||
connectionTarget?: ElementState;
|
||||
isDrawingConnection?: boolean;
|
||||
didConnectionLeaveHighlight?: boolean;
|
||||
|
||||
constructor(scene: Scene) {
|
||||
this.scene = scene;
|
||||
@ -118,11 +119,19 @@ export class Connections {
|
||||
this.connectionLine.setAttribute('x2', `${x}`);
|
||||
this.connectionLine.setAttribute('y2', `${y}`);
|
||||
|
||||
const connectionLineX1 = this.connectionLine.x1.baseVal.value;
|
||||
const connectionLineY1 = this.connectionLine.y1.baseVal.value;
|
||||
if (!this.didConnectionLeaveHighlight) {
|
||||
const connectionLength = Math.hypot(x - connectionLineX1, y - connectionLineY1);
|
||||
if (connectionLength > CONNECTION_ANCHOR_HIGHLIGHT_OFFSET && this.connectionSVG) {
|
||||
this.didConnectionLeaveHighlight = true;
|
||||
this.connectionSVG.style.display = 'block';
|
||||
this.isDrawingConnection = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!event.buttons) {
|
||||
if (this.connectionSource && this.connectionSource.div && this.connectionSource.div.parentElement) {
|
||||
const connectionLineX1 = this.connectionLine.x1.baseVal.value;
|
||||
const connectionLineY1 = this.connectionLine.y1.baseVal.value;
|
||||
|
||||
const sourceRect = this.connectionSource.div.getBoundingClientRect();
|
||||
const parentRect = this.connectionSource.div.parentElement.getBoundingClientRect();
|
||||
|
||||
@ -174,9 +183,10 @@ export class Connections {
|
||||
if (!options.connections) {
|
||||
options.connections = [];
|
||||
}
|
||||
this.connectionSource.options.connections = [...options.connections, connection];
|
||||
|
||||
this.connectionSource.onChange(this.connectionSource.options);
|
||||
if (this.didConnectionLeaveHighlight) {
|
||||
this.connectionSource.options.connections = [...options.connections, connection];
|
||||
this.connectionSource.onChange(this.connectionSource.options);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.connectionSVG) {
|
||||
@ -198,10 +208,8 @@ export class Connections {
|
||||
const connectionStartTargetBox = selectedTarget.getBoundingClientRect();
|
||||
const parentBoundingRect = this.scene.div.parentElement.getBoundingClientRect();
|
||||
|
||||
// TODO: Make this not as magic numbery -> related to the height / width of highlight ellipse
|
||||
const connectionAnchorHighlightOffset = 8;
|
||||
const x = connectionStartTargetBox.x - parentBoundingRect.x + connectionAnchorHighlightOffset;
|
||||
const y = connectionStartTargetBox.y - parentBoundingRect.y + connectionAnchorHighlightOffset;
|
||||
const x = connectionStartTargetBox.x - parentBoundingRect.x + CONNECTION_ANCHOR_HIGHLIGHT_OFFSET;
|
||||
const y = connectionStartTargetBox.y - parentBoundingRect.y + CONNECTION_ANCHOR_HIGHLIGHT_OFFSET;
|
||||
|
||||
const mouseX = clientX - parentBoundingRect.x;
|
||||
const mouseY = clientY - parentBoundingRect.y;
|
||||
@ -210,9 +218,7 @@ export class Connections {
|
||||
this.connectionLine.setAttribute('y1', `${y}`);
|
||||
this.connectionLine.setAttribute('x2', `${mouseX}`);
|
||||
this.connectionLine.setAttribute('y2', `${mouseY}`);
|
||||
this.connectionSVG.style.display = 'block';
|
||||
|
||||
this.isDrawingConnection = true;
|
||||
this.didConnectionLeaveHighlight = false;
|
||||
}
|
||||
|
||||
this.scene.selecto?.rootContainer?.addEventListener('mousemove', this.connectionListener);
|
||||
|
Loading…
Reference in New Issue
Block a user