Skip to content

Commit

Permalink
fix(rendering): render external node labels above arrows (#932)
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomaash authored Aug 8, 2020
1 parent d655613 commit 565bdbd
Show file tree
Hide file tree
Showing 13 changed files with 227 additions and 103 deletions.
185 changes: 110 additions & 75 deletions cypress/integration/visual/z-index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,83 +1,118 @@
const EXTERNAL_LABEL_SHAPES = new Set<string>([
"diamond",
"dot",
"hexagon",
"square",
"star",
"triangle",
"triangleDown",
]);
const INTERNAL_LABEL_SHAPES = new Set<string>([
"box",
"circle",
"database",
"ellipse",
"text",
]);

const EXTERNAL_LABEL = new Array(15)
.fill(null)
.map((): string => "This label should be above edge labels and arrows.")
.join("\n");
const INTERNAL_LABEL = [
"This",
"label",
"should",
"be",
"above",
"edge",
"labels",
"but",
"bellow",
"arrows.",
].join("\n");

context("Z-index", (): void => {
it("node labels > nodes > edge labels > edge arrows > edges", (): void => {
cy.visSimpleCanvasSnapshot(
"node-labels_nodes_edge-labels_edge-arrows_edges",
{
nodes: [
describe("external node labels > edge arrows > internal node labels > nodes > edge labels > edges", (): void => {
for (const shape of [...EXTERNAL_LABEL_SHAPES, ...INTERNAL_LABEL_SHAPES]) {
it(shape, function (): void {
cy.visSimpleCanvasSnapshot(
`z-index_${shape}`,
{
id: 1,
fixed: true,
x: 0,
y: -300,
shape: "dot",
label: new Array(15)
.fill(null)
.map(
(): string =>
"This label should be above edge labels and arrows."
)
.join("\n"),
font: {
color: "green",
size: 40,
},
},
{
id: 3,
fixed: true,
x: 100,
y: 300,
shape: "box",
label: new Array(5)
.fill(null)
.map(
(): string =>
"This label should be above edge labels but bellow arrows."
)
.join("\n"),
font: {
color: "black",
size: 20,
},
},
],
edges: [
{
id: 2,
from: 1,
to: 3,
label: new Array(80)
.fill(null)
.map(
(): string =>
"This label should be bellow nodes and their labels but above edge arrows."
)
.join("\n"),
font: {
color: "red",
size: 10,
},
arrows: {
from: {
enabled: true,
scaleFactor: 6,
nodes: [
{
id: 1,
fixed: true,
x: 0,
y: -300,
shape,
label: EXTERNAL_LABEL_SHAPES.has(shape)
? EXTERNAL_LABEL
: INTERNAL_LABEL,
font: {
color: "green",
size: 40,
},
},
middle: {
enabled: true,
scaleFactor: 6,
{
id: 3,
fixed: true,
x: 100,
y: 300,
shape: "box",
label: new Array(5)
.fill(null)
.map(
(): string =>
"This label should be above edge labels but bellow arrows."
)
.join("\n"),
font: {
color: "black",
size: 20,
},
},
to: {
enabled: true,
scaleFactor: 6,
],
edges: [
{
id: 2,
from: 1,
to: 3,
label: new Array(80)
.fill(null)
.map(
(): string =>
"This label should be bellow nodes and their labels but above edge arrows."
)
.join("\n"),
font: {
color: "red",
size: 10,
},
arrows: {
from: {
enabled: true,
scaleFactor: 6,
},
middle: {
enabled: true,
scaleFactor: 6,
},
to: {
enabled: true,
scaleFactor: 6,
},
},
endPointOffset: {
from: -50,
to: -50,
},
},
},
endPointOffset: {
from: -50,
to: -50,
},
],
},
],
}
);
{ requireNewerVersionThan: "8.0.1" }
);
});
}
});
});
2 changes: 1 addition & 1 deletion cypress/support/commands/vis-simple-canvas-snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function visSimpleCanvasSnapshot(
deepObjectAssign<MoveToOptions>(
{
position: { x: 0, y: 0 },
scale: 1
scale: 1,
},
options.moveTo ?? {}
)
Expand Down
42 changes: 37 additions & 5 deletions lib/network/modules/CanvasRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,10 @@ class CanvasRenderer {

this.redrawRequested = false;

const drawLater = {
drawExternalLabels: null,
}

// when the container div was hidden, this fixes it back up!
if (this.canvas.frame.canvas.width === 0 || this.canvas.frame.canvas.height === 0) {
this.canvas.setSize();
Expand Down Expand Up @@ -284,7 +288,8 @@ class CanvasRenderer {
}

if (this.dragging === false || (this.dragging === true && this.options.hideNodesOnDrag === false)) {
this._drawNodes(ctx, hidden);
const { drawExternalLabels } = this._drawNodes(ctx, hidden);
drawLater.drawExternalLabels = drawExternalLabels;
}

// draw the arrows last so they will be at the top
Expand All @@ -297,6 +302,10 @@ class CanvasRenderer {
}
}

if (drawLater.drawExternalLabels != null) {
drawLater.drawExternalLabels();
}

if (hidden === false) {
this._drawSelectionBox(ctx)
}
Expand Down Expand Up @@ -352,6 +361,8 @@ class CanvasRenderer {
* @param {CanvasRenderingContext2D} ctx 2D context of a HTML canvas
* @param {boolean} [alwaysShow]
* @private
*
* @returns {Object} Callbacks to draw later on higher layers.
*/
_drawNodes(ctx, alwaysShow = false) {
const nodes = this.body.nodes;
Expand All @@ -367,6 +378,8 @@ class CanvasRenderer {
});
const viewableArea = {top:topLeft.y,left:topLeft.x,bottom:bottomRight.y,right:bottomRight.x};

const drawExternalLabels = [];

// draw unselected nodes;
for (let i = 0; i < nodeIndices.length; i++) {
node = nodes[nodeIndices[i]];
Expand All @@ -378,10 +391,16 @@ class CanvasRenderer {
}
else {
if (alwaysShow === true) {
node.draw(ctx);
const drawLater = node.draw(ctx);
if (drawLater.drawExternalLabel != null) {
drawExternalLabels.push(drawLater.drawExternalLabel)
}
}
else if (node.isBoundingBoxOverlappingWith(viewableArea) === true) {
node.draw(ctx);
const drawLater = node.draw(ctx);
if (drawLater.drawExternalLabel != null) {
drawExternalLabels.push(drawLater.drawExternalLabel)
}
}
else {
node.updateBoundingBox(ctx, node.selected);
Expand All @@ -396,15 +415,28 @@ class CanvasRenderer {
// draw the selected nodes on top
for (i = 0; i < selectedLength; i++) {
node = nodes[selected[i]];
node.draw(ctx);
const drawLater = node.draw(ctx);
if (drawLater.drawExternalLabel != null) {
drawExternalLabels.push(drawLater.drawExternalLabel)
}
}

// draw hovered nodes above everything else: fixes https://github.com/visjs/vis-network/issues/226
for (i = 0; i < hoveredLength; i++) {
node = nodes[hovered[i]];
node.draw(ctx);
const drawLater = node.draw(ctx);
if (drawLater.drawExternalLabel != null) {
drawExternalLabels.push(drawLater.drawExternalLabel)
}
}

return {
drawExternalLabels: () => {
for (const draw of drawExternalLabels) {
draw();
}
},
};
}


Expand Down
11 changes: 10 additions & 1 deletion lib/network/modules/components/Node.js
Original file line number Diff line number Diff line change
Expand Up @@ -639,10 +639,19 @@ class Node {
* Draw this node in the given canvas
* The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
* @param {CanvasRenderingContext2D} ctx
*
* @returns {Object} Callbacks to draw later on higher layers.
*/
draw(ctx) {
const values = this.getFormattingValues();
this.shape.draw(ctx, this.x, this.y, this.selected, this.hover, values);
return this.shape.draw(
ctx,
this.x,
this.y,
this.selected,
this.hover,
values
) || {};
}


Expand Down
4 changes: 3 additions & 1 deletion lib/network/modules/components/nodes/shapes/Diamond.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ class Diamond extends ShapeBase {
* @param {boolean} selected
* @param {boolean} hover
* @param {ArrowOptions} values
*
* @returns {Object} Callbacks to draw later on higher layers.
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'diamond', 4, x, y, selected, hover, values);
return this._drawShape(ctx, 'diamond', 4, x, y, selected, hover, values);
}

/**
Expand Down
4 changes: 3 additions & 1 deletion lib/network/modules/components/nodes/shapes/Dot.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ class Dot extends ShapeBase {
* @param {boolean} selected
* @param {boolean} hover
* @param {ArrowOptions} values
*
* @returns {Object} Callbacks to draw later on higher layers.
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'circle', 2, x, y, selected, hover, values);
return this._drawShape(ctx, 'circle', 2, x, y, selected, hover, values);
}

/**
Expand Down
4 changes: 3 additions & 1 deletion lib/network/modules/components/nodes/shapes/Hexagon.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ class Hexagon extends ShapeBase {
* @param {boolean} selected
* @param {boolean} hover
* @param {ArrowOptions} values
*
* @returns {Object} Callbacks to draw later on higher layers.
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'hexagon', 4, x, y, selected, hover, values);
return this._drawShape(ctx, 'hexagon', 4, x, y, selected, hover, values);
}

/**
Expand Down
Loading

0 comments on commit 565bdbd

Please sign in to comment.