Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 4 additions & 0 deletions docs/styles.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ the following properties:
| `colorHover` | Color | string | Node background color on mouse hover event. If not defined `color` is used. |
| `colorSelected` | Color | string | Node background color on mouse click event. If not defined `color` is used. |
| `fontBackgroundColor` | Color | string | Node text (label) background color. |
| `fontBackgroundBorderWidth` | number | Node text (label) background border width. |
| `fontBackgroundBorderColor` | Color | string | Node text (label) background border color. |
| `fontBackgroundBorderRadius` | number | Node text (label) background border radius. |
| `fontBackgroundPadding` | number | Node text (label) background padding. |
| `fontColor` | Color | string | Node text (label) font color. The default is `#000000`. |
| `fontFamily` | string | Node text (label) font family. The default is `"Roboto, sans-serif"`. |
| `fontSize` | number | Node text (label) font size. The default is `4`. |
Expand Down
39 changes: 32 additions & 7 deletions examples/example-custom-styled-graph.html
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
<!DOCTYPE html>
<html lang='en' type="module">

<head>
<base href=".">
<meta charset='UTF-8'>
<title>Orb | Simple graph with custom default style on default canvas</title>
<script type="text/javascript" src="./orb.js"></script>
</head>
<style>
html, body {
html,
body {
height: 100%;
margin: 0;
}
</style>

<body>
<div style="display: flex; flex-direction: column; align-items: center; height: 100%;">
<h1>Example 2 - Basic + Custom default style</h1>
Expand All @@ -30,7 +33,7 @@ <h1>Example 2 - Basic + Custom default style</h1>

const nodes = [
{ id: 0, label: 'Node A' },
{ id: 1, label: 'Node B' },
{ id: 1, label: 'Node B - A Special Node' },
{ id: 2, label: 'Node C' },
];
const edges = [
Expand Down Expand Up @@ -63,12 +66,19 @@ <h1>Example 2 - Basic + Custom default style</h1>
size: 6,
};

if (node.data.label === 'Node A') {
if (node.data.label === 'Node B - A Special Node') {
return {
...basicStyle,
size: 10,
size: 4,
borderWidth: 0.3,
color: '#00FF2B',
zIndex: 1,
fontBackgroundColor: 'rgb(0, 255, 0)',
fontBackgroundBorderWidth: 0.1,
fontBackgroundBorderColor: 'grey',
fontBackgroundBorderRadius: 2,
fontBackgroundPadding: 0.5,
fontSize: 2,
};
}

Expand All @@ -77,7 +87,7 @@ <h1>Example 2 - Basic + Custom default style</h1>
};
},
getEdgeStyle(edge) {
return {
const basicStyles = {
color: '#999999',
colorHover: '#1d1d1d',
colorSelected: '#1d1d1d',
Expand All @@ -86,7 +96,21 @@ <h1>Example 2 - Basic + Custom default style</h1>
widthHover: 0.9,
widthSelected: 0.9,
label: edge.data.label,
};
}

if (edge.data.label === 'A -> B') {
return {
...basicStyles,
fontBackgroundColor: 'rgb(0, 255, 0)',
fontBackgroundBorderWidth: 0.1,
fontBackgroundBorderColor: 'grey',
fontBackgroundBorderRadius: 10,
fontBackgroundPadding: 0.5,
fontSize: 2,
}
}

else return { ...basicStyles };
},
});

Expand All @@ -98,4 +122,5 @@ <h1>Example 2 - Basic + Custom default style</h1>
});
</script>
</body>
</html>

</html>
4 changes: 4 additions & 0 deletions src/models/edge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ export type IEdgeStyle = Partial<{
colorHover: Color | string;
colorSelected: Color | string;
fontBackgroundColor: Color | string;
fontBackgroundBorderWidth: number;
fontBackgroundBorderColor: Color | string;
fontBackgroundBorderRadius: number;
fontBackgroundPadding: number;
fontColor: Color | string;
fontFamily: string;
fontSize: number;
Expand Down
4 changes: 4 additions & 0 deletions src/models/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ export type INodeStyle = Partial<{
colorHover: Color | string;
colorSelected: Color | string;
fontBackgroundColor: Color | string;
fontBackgroundBorderWidth: number;
fontBackgroundBorderColor: Color | string;
fontBackgroundBorderRadius: number;
fontBackgroundPadding: number;
fontColor: Color | string;
fontFamily: string;
fontSize: number;
Expand Down
4 changes: 4 additions & 0 deletions src/renderer/canvas/edge/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ const drawEdgeLabel = <N extends INodeBase, E extends IEdgeBase>(
textBaseline: LabelTextBaseline.MIDDLE,
properties: {
fontBackgroundColor: edge.style.fontBackgroundColor,
fontBackgroundBorderWidth: edge.style.fontBackgroundBorderWidth,
fontBackgroundBorderColor: edge.style.fontBackgroundBorderColor,
fontBackgroundBorderRadius: edge.style.fontBackgroundBorderRadius,
fontBackgroundPadding: edge.style.fontBackgroundPadding,
fontColor: edge.style.fontColor,
fontFamily: edge.style.fontFamily,
fontSize: edge.style.fontSize,
Expand Down
63 changes: 54 additions & 9 deletions src/renderer/canvas/label.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export enum LabelTextBaseline {

export interface ILabelProperties {
fontBackgroundColor: Color | string;
fontBackgroundBorderWidth: number;
fontBackgroundBorderColor: Color | string;
fontBackgroundBorderRadius: number;
fontBackgroundPadding: number;
fontColor: Color | string;
fontFamily: string;
fontSize: number;
Expand Down Expand Up @@ -75,19 +79,53 @@ const drawTextBackground = (context: CanvasRenderingContext2D, label: Label) =>

context.fillStyle = label.properties.fontBackgroundColor.toString();
const margin = label.fontSize * FONT_BACKGROUND_MARGIN;
const height = label.fontSize + 2 * margin;

let height = label.fontSize + 2 * margin;
const lineHeight = label.fontSize * FONT_LINE_SPACING;

const baselineHeight = label.textBaseline === LabelTextBaseline.MIDDLE ? label.fontSize / 2 : 0;

for (let i = 0; i < label.textLines.length; i++) {
const line = label.textLines[i];
const width = context.measureText(line).width + 2 * margin;
context.fillRect(
label.position.x - width / 2,
label.position.y - baselineHeight - margin + i * lineHeight,
width,
height,
);

let width = context.measureText(line).width + 2 * margin;
Comment thread
shashankshukla96 marked this conversation as resolved.
let x = label.position.x - width / 2;
const y = label.position.y - baselineHeight - margin + i * lineHeight;

if (label.properties.fontBackgroundPadding) {
width += label.properties.fontBackgroundPadding * 2;
height += label.properties.fontBackgroundPadding * 2;
Comment thread
shashankshukla96 marked this conversation as resolved.
x -= label.properties.fontBackgroundPadding;
}

if (label.properties.fontBackgroundBorderRadius) {
const borderRadius = Math.min(label.properties.fontBackgroundBorderRadius, width / 2, height / 2);

context.beginPath();
context.lineWidth = label.properties.fontBackgroundBorderWidth ?? 0;

context.moveTo(x + borderRadius, y);
context.lineTo(x + width - borderRadius, y);
context.quadraticCurveTo(x + width, y, x + width, y + borderRadius);
context.lineTo(x + width, y + height - borderRadius);
context.quadraticCurveTo(x + width, y + height, x + width - borderRadius, y + height);
context.lineTo(x + borderRadius, y + height);
context.quadraticCurveTo(x, y + height, x, y + height - borderRadius);
context.lineTo(x, y + borderRadius);
context.quadraticCurveTo(x, y, x + borderRadius, y);
context.closePath();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can use drawRoundRect from shapes here.

context.fillStyle = (label.properties.fontBackgroundColor ?? DEFAULT_FONT_COLOR).toString();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure you want to use DEFAULT_FONT_COLOR here? If default font color is black, and the background is black too, then by default, the text won't be visible.

context.strokeStyle = (label.properties.fontBackgroundBorderColor ?? DEFAULT_FONT_COLOR).toString();
context.fill();
context.stroke();
} else if (label.properties.fontBackgroundBorderWidth && !label.properties.fontBackgroundBorderRadius) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You already have if(label.properties.fontBackgroundBorderRadius) on line 101, to the check for (!label.properties.fontBackgroundBorderRadius` is not needed here, it is irrelevant.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is hard to figure out what will be the shape drawn from these two ifs and else so I propose splitting it so it is much easier to understand what final shape will be drawn, e.g.

// setup and preps

const isBackgroundShapeDrawn = ....
if (!isBackgroundShapeDrawn) {
  continue;
}

// I think this function will also handle radius = 0 to draw proper rect
drawRoundRect(...);

if (backgroundColor) {
  setFill = 
  fill();
}

If (borderWidth) {
  setStrokeStyle = 
  stroke();
}

context.lineWidth = label.properties.fontBackgroundBorderWidth;
context.strokeStyle = (label.properties.fontBackgroundBorderColor ?? DEFAULT_FONT_COLOR).toString();

context.strokeRect(x, y, width, height);
} else {
context.fillRect(x, y, width, height);
}
}
};

Expand All @@ -102,9 +140,16 @@ const drawText = (context: CanvasRenderingContext2D, label: Label) => {
context.textAlign = 'center';
const lineHeight = label.fontSize * FONT_LINE_SPACING;

const x = label.position.x;
let y = label.position.y;

if (label.properties.fontBackgroundPadding) {
y += label.properties.fontBackgroundPadding;
}

for (let i = 0; i < label.textLines.length; i++) {
const line = label.textLines[i];
context.fillText(line, label.position.x, label.position.y + i * lineHeight);
context.fillText(line, x, y + i * lineHeight);
}
};

Expand Down
4 changes: 4 additions & 0 deletions src/renderer/canvas/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ const drawNodeLabel = <N extends INodeBase, E extends IEdgeBase>(
textBaseline: LabelTextBaseline.TOP,
properties: {
fontBackgroundColor: node.style.fontBackgroundColor,
fontBackgroundBorderWidth: node.style.fontBackgroundBorderWidth,
fontBackgroundBorderColor: node.style.fontBackgroundBorderColor,
fontBackgroundBorderRadius: node.style.fontBackgroundBorderRadius,
fontBackgroundPadding: node.style.fontBackgroundPadding,
fontColor: node.style.fontColor,
fontFamily: node.style.fontFamily,
fontSize: node.style.fontSize,
Expand Down