Skip to content

Support flow connections (render only) #156

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions editor-packages/editor-canvas/flow-connections/arrow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React from "react";
import type { XY } from "../types";

export function Arrow({
b,
color,
size,
width,
direction,
}: {
b: XY;
color: React.CSSProperties["color"];
size: number;
width: number;
direction: "n" | "s" | "e" | "w";
}) {
return (
<path
stroke={color}
strokeWidth={width}
d={make_arrow_svg_path_data(b, direction, {
width: size,
height: size / 2,
})}
/>
);
}

/**
*
* the result will have 3 modifiers,
* if the arrow is facing right, the modifiers will be:
* - M - starting point [edge_x - height, edge_y + width / 2]
* - L - edge [edge_x, edge_y]
* - L - ending point [edge_x - height, edge_y - width / 2]
*
* @param edge the edge of a arrow (triangle)
* @param width
*/
function make_arrow_svg_path_data(
edge: XY,
direction: "n" | "s" | "e" | "w",
{ width, height }: { width: number; height: number }
) {
const [x, y] = edge;
const w = width / 2;
switch (direction) {
case "e": {
return `M${x - height},${y + w} L${x},${y} L${x - height},${y - w}`;
}
case "w": {
return `M${x + height},${y + w} L${x},${y} L${x + height},${y - w}`;
}
case "n": {
return `M${x - w},${y + height} L${x},${y} L${x + w},${y + height}`;
}
case "s": {
return `M${x - w},${y - height} L${x},${y} L${x + w},${y - height}`;
}
default: {
throw new Error(`invalid direction: ${direction}`);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { color_connection_line } from "../theme";
import type { XY } from "../types";
import { Arrow } from "./arrow";
import { get_direction } from "./math";
import type { ConnectionLineStyleProps } from "./props";

export function BezierCurvedLine({
a,
b,
width = 2,
color = color_connection_line,
}: { a: XY; b: XY } & ConnectionLineStyleProps) {
const direction = get_direction(a, b);

return (
<svg
fill="transparent"
style={{
overflow: "visible",
position: "absolute",
pointerEvents: "none",
// transform: `translate(${a[0]}px, ${a[1]}px)`,
zIndex: 10,
}}
>
<path
stroke={color}
strokeWidth={width}
d={make_bazier_curved_svg_path_data(
a,
b,
direction_to_axis_map[direction]
)}
/>
<Arrow
color={color}
size={12}
b={b}
width={width}
direction={direction}
/>
</svg>
);
}

const direction_to_axis_map = {
n: "v",
s: "v",
e: "h",
w: "h",
} as const;

/**
* make a svg path data to connect point a to point b
*
* the output will contain 2 commands
* - M - starting point
* - C - curve
*
* e.g. for a a[0, 0], b[1000, 500], (1000x500 box)
* - `"M 0 0 C 500 0 500 500 1000 500"`
* - M a[0], a[1] (start point)
* - C0 a[0] + w / 2, a[1]
* - C1 a[0] + w / 2, b[1]
* - C2 b[0], b[1] (end point)
*
* @param a - starting point
* @param b - ending point
*/
function make_bazier_curved_svg_path_data(a: XY, b: XY, axis: "h" | "v" = "h") {
const [x0, y0] = a;
const [x1, y1] = b;
const w = axis === "h" ? x1 - x0 : y1 - y0;

if (axis === "h") {
return `M ${x0},${y0} C ${x0 + w / 2},${y0} ${
x0 + w / 2
},${y1} ${x1},${y1}`;
} else if (axis === "v") {
return `M ${x0},${y0} C ${x0},${y0 + w / 2} ${x1},${
y0 + w / 2
} ${x1},${y1}`;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React from "react";
import type { XY } from "../types";
import { Arrow } from "./arrow";
import { get_direction } from "./math";

/**
* @deprecated - not implemented
* @param param0
* @returns
*/
export function EdgeCurvedConnectionLine({
a,
b,
width = 2,
color = "blue",
}: { a: XY; b: XY } & {
width?: number;
color?: React.CSSProperties["color"];
}) {
const direction = get_direction(a, b);
return (
<svg
fill="transparent"
height={Math.abs(b[1] - a[1])}
width={Math.abs(b[0] - a[0])}
style={{
overflow: "visible",
position: "absolute",
pointerEvents: "none",
transform: `translate(${a[0]}px, ${a[1]}px)`,
zIndex: 10,
}}
>
<Line a={a} b={b} />
<Arrow
color={color}
size={12}
b={b}
width={width}
direction={direction}
/>
</svg>
);
}

function Line({ a, b }: { a: XY; b: XY }) {
return <path d="" />;
}

/**
*
* makes the svg path data that connects point a to point b, with extra parameters, curve delta and edge inset
*
* the shape looks line
* ```
* (a) ---
* |
* |
* |
* |
* |
* --- (b)
* ```
*
* the line components are..
* 0. M | starting point
* 1. L L | the line from `a - edge` to `a` - [a - edge, a]
* 2. C | the curve to before 3
* 3. L | the line from `a` to `b` - [a, b]
* 4. C | the curve to after 3
* 5. L L | the line from `b` to `b + edge` - [b, b + edge]
*
* the output command is:
* - M - the start point (a)
* - L - line start
* - L - draw line to the curving point
* - C - curve
* - L - line between two curves
* - C - curve
* - L - line start
* - L - line end point
*
* e.g. the output of this function is:
* - `"M 0 0 L 0 0 L 8 0 L 8 0 C 17.1638 0 25.4139 5.5525 28.8641 14.042 L 165.907 351.249 C 169.358 359.739 177.608 365.291 186.772 365.291 L 186.772 365.291 L 194.772 365.291"`
*
* @param a the starting point a
* @param b the ending point b
* @param curve the curve delta
* @param edge the edge (margin) value
*/
function make_svg_path_data(a: XY, b: XY, edge) {}
2 changes: 2 additions & 0 deletions editor-packages/editor-canvas/flow-connections/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { EdgeCurvedConnectionLine } from "./connection-line-edge-curved";
export { BezierCurvedLine } from "./connection-line-bezier-curved";
27 changes: 27 additions & 0 deletions editor-packages/editor-canvas/flow-connections/knob.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {
color_connection_knob_fill,
color_connection_knob_stroke,
} from "../theme";
import type { XY } from "../types";

export function Knob({ point, size = 6 }: { point: XY; size: number }) {
return (
<svg
fill="transparent"
style={{
overflow: "visible",
position: "absolute",
pointerEvents: "none",
transform: `translate(${point[0]}px, ${point[1]}px)`,
zIndex: 10,
}}
>
<circle
r={size}
stroke={color_connection_knob_stroke}
fill={color_connection_knob_fill}
strokeWidth={2}
/>
</svg>
);
}
Empty file.
43 changes: 43 additions & 0 deletions editor-packages/editor-canvas/flow-connections/math.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { XY } from "../types";

/**
* get the direction based on two points (vector), a and b.
* returns the most powerful direction, e.g. [0, 0], [10, 50] -> "s"
* if the power is the same, return "e" | "w" first, then "s" | "n".
*
* examples
* - [0, 0], [10, 50] -> "s"
* - [0, 0], [10, 0] -> "e"
* - [0, 0], [0, 50] -> "s"
* - [0, 0], [0, 0] -> "e"
* - [0, 0], [-10, 50] -> "n"
* - [0, 0], [-10, 0] -> "w"
* - [0, 0], [-10, -50] -> "n"
* - [0, 0], [-10, 0] -> "w"
* - [0, 0], [-100, -100] -> "w"
*
* @param a
* @param b
* @returns
*/
export function get_direction(a: XY, b: XY): "n" | "s" | "e" | "w" {
const [x, y] = a;
const [x2, y2] = b;

const x_diff = x2 - x;
const y_diff = y2 - y;

if (Math.abs(x_diff) >= Math.abs(y_diff)) {
if (x_diff > 0) {
return "e";
} else {
return "w";
}
}

if (y_diff > 0) {
return "s";
}

return "n";
}
6 changes: 6 additions & 0 deletions editor-packages/editor-canvas/flow-connections/props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from "react";

export interface ConnectionLineStyleProps {
width?: number;
color?: React.CSSProperties["color"];
}
3 changes: 3 additions & 0 deletions editor-packages/editor-canvas/theme/default-theme.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
export const color_layer_highlight = "#0099ff";
export const color_layer_readonly_highlight = "#0099ff";
export const color_connection_line = "#34AEFF";
export const color_connection_knob_stroke = "#34AEFF";
export const color_connection_knob_fill = "white";
export const color_frame_title = {
default: "grey",
highlight: color_layer_highlight,
Expand Down