diff --git a/docs/network/nodes.html b/docs/network/nodes.html index c3cd63a1..4dbcef5a 100644 --- a/docs/network/nodes.html +++ b/docs/network/nodes.html @@ -459,6 +459,36 @@ network.setOptions(options); undefined When using the hierarchical layout, the level determines where the node is going to be positioned. + + margin + Object or Number + 5 + If a number is specified, the margins of the label are set to that value on all sides. These options are only used when the shape is set to box, circle, database, icon or text. + + + margin.top + Number + 5 + The top margin of the label is set to this value. + + + margin.right + Number + 5 + The right margin of the label is set to this value. + + + margin.bottom + Number + 5 + The bottom margin of the label is set to this value. + + + margin.left + Number + 5 + The left margin of the label is set to this value. + mass Number diff --git a/examples/network/labels/labelMargins.html b/examples/network/labels/labelMargins.html new file mode 100644 index 00000000..8be983a7 --- /dev/null +++ b/examples/network/labels/labelMargins.html @@ -0,0 +1,63 @@ + + + + Network | Label margins + + + + + + + + + + +

The labels of box, circle, database, icon and text nodes may have different margin values. + Top, right, bottom and left margins may be different for each node.

+

Setting the margin value in the network's nodes property sets it as the default.

+

Setting a the value to a number uses that number for the margins. If the value is an object, a different value for each margin will be set.

+

Note that negative values appropriately push labels outside the node. + +

+ + + + + diff --git a/lib/network/modules/NodesHandler.js b/lib/network/modules/NodesHandler.js index e548bd41..acd5a307 100644 --- a/lib/network/modules/NodesHandler.js +++ b/lib/network/modules/NodesHandler.js @@ -63,6 +63,12 @@ class NodesHandler { label: undefined, labelHighlightBold: true, level: undefined, + margin: { + top: 5, + right: 5, + bottom: 5, + left: 5 + }, mass: 1, physics: true, scaling: { diff --git a/lib/network/modules/components/nodes/shapes/Box.js b/lib/network/modules/components/nodes/shapes/Box.js index d2d15740..a8b6e56d 100644 --- a/lib/network/modules/components/nodes/shapes/Box.js +++ b/lib/network/modules/components/nodes/shapes/Box.js @@ -5,15 +5,15 @@ import NodeBase from '../util/NodeBase' class Box extends NodeBase { constructor (options, body, labelModule) { super(options,body,labelModule); + this._setMargins() } resize(ctx, selected) { if (this.width === undefined) { - let margin = 5; - let textSize = this.labelModule.getTextSize(ctx,selected); - this.width = textSize.width + 2 * margin; - this.height = textSize.height + 2 * margin; - this.radius = 0.5*this.width; + this.textSize = this.labelModule.getTextSize(ctx,selected); + this.width = this.textSize.width + this.margin.right + this.margin.left; + this.height = this.textSize.height + this.margin.top + this.margin.bottom; + this.radius = this.width / 2; } } @@ -55,13 +55,14 @@ class Box extends NodeBase { ctx.restore(); this.updateBoundingBox(x,y,ctx,selected); - this.labelModule.draw(ctx, x, y, selected); + this.labelModule.draw(ctx, this.left + this.textSize.width / 2 + this.margin.left, + this.top + this.textSize.height / 2 + this.margin.top, selected); } updateBoundingBox(x,y, ctx, selected) { this.resize(ctx, selected); - this.left = x - this.width * 0.5; - this.top = y - this.height * 0.5; + this.left = x - this.width / 2; + this.top = y - this.height / 2; let borderRadius = this.options.shapeProperties.borderRadius; // only effective for box this.boundingBox.left = this.left - borderRadius; diff --git a/lib/network/modules/components/nodes/shapes/Circle.js b/lib/network/modules/components/nodes/shapes/Circle.js index 221e92df..2c42778b 100644 --- a/lib/network/modules/components/nodes/shapes/Circle.js +++ b/lib/network/modules/components/nodes/shapes/Circle.js @@ -5,18 +5,19 @@ import CircleImageBase from '../util/CircleImageBase' class Circle extends CircleImageBase { constructor(options, body, labelModule) { super(options, body, labelModule) + this._setMargins(); } resize(ctx, selected) { if (this.width === undefined) { - var margin = 5; - var textSize = this.labelModule.getTextSize(ctx, selected); - var diameter = Math.max(textSize.width, textSize.height) + 2 * margin; + this.textSize = this.labelModule.getTextSize(ctx, selected); + var diameter = Math.max(this.textSize.width + this.margin.right + this.margin.left, + this.textSize.height + this.margin.top + this.margin.bottom); this.options.size = diameter / 2; this.width = diameter; this.height = diameter; - this.radius = 0.5*this.width; + this.radius = this.width / 2; } } @@ -33,7 +34,8 @@ class Circle extends CircleImageBase { this.boundingBox.bottom = y + this.options.size; this.updateBoundingBox(x,y); - this.labelModule.draw(ctx, x, y, selected); + this.labelModule.draw(ctx, this.left + this.textSize.width / 2 + this.margin.left, + this.top + this.textSize.height / 2 + this.margin.top, selected); } updateBoundingBox(x,y) { @@ -49,4 +51,4 @@ class Circle extends CircleImageBase { } } -export default Circle; \ No newline at end of file +export default Circle; diff --git a/lib/network/modules/components/nodes/shapes/Database.js b/lib/network/modules/components/nodes/shapes/Database.js index dabc02ff..f17e5457 100644 --- a/lib/network/modules/components/nodes/shapes/Database.js +++ b/lib/network/modules/components/nodes/shapes/Database.js @@ -5,16 +5,16 @@ import NodeBase from '../util/NodeBase' class Database extends NodeBase { constructor (options, body, labelModule) { super(options, body, labelModule); + this._setMargins(); } resize(ctx, selected) { if (this.width === undefined) { - var margin = 5; - var textSize = this.labelModule.getTextSize(ctx, selected); - var size = textSize.width + 2 * margin; + this.textSize = this.labelModule.getTextSize(ctx, selected); + var size = this.textSize.width + this.margin.right + this.margin.left; this.width = size; this.height = size; - this.radius = 0.5*this.width; + this.radius = this.width / 2; } } @@ -31,7 +31,7 @@ class Database extends NodeBase { ctx.strokeStyle = selected ? this.options.color.highlight.border : hover ? this.options.color.hover.border : this.options.color.border; ctx.fillStyle = selected ? this.options.color.highlight.background : hover ? this.options.color.hover.background : this.options.color.background; - ctx.database(x - this.width / 2, y - this.height * 0.5, this.width, this.height); + ctx.database(x - this.width / 2, y - this.height / 2, this.width, this.height); // draw shadow if enabled this.enableShadow(ctx); @@ -53,7 +53,8 @@ class Database extends NodeBase { ctx.restore(); this.updateBoundingBox(x,y,ctx,selected); - this.labelModule.draw(ctx, x, y, selected); + this.labelModule.draw(ctx, this.left + this.textSize.width / 2 + this.margin.left, + this.top + this.textSize.height / 2 + this.margin.top, selected); } updateBoundingBox(x,y,ctx, selected) { diff --git a/lib/network/modules/components/nodes/shapes/Icon.js b/lib/network/modules/components/nodes/shapes/Icon.js index c01df052..a5aae214 100644 --- a/lib/network/modules/components/nodes/shapes/Icon.js +++ b/lib/network/modules/components/nodes/shapes/Icon.js @@ -5,17 +5,17 @@ import NodeBase from '../util/NodeBase' class Icon extends NodeBase { constructor(options, body, labelModule) { super(options, body, labelModule); + this._setMargins(); } resize(ctx) { if (this.width === undefined) { - var margin = 5; - var iconSize = { + this.iconSize = { width: Number(this.options.icon.size), height: Number(this.options.icon.size) }; - this.width = iconSize.width + 2 * margin; - this.height = iconSize.height + 2 * margin; + this.width = this.iconSize.width + this.margin.right + this.margin.left; + this.height = this.iconSize.height + this.margin.top + this.margin.bottom; this.radius = 0.5*this.width; } } @@ -24,13 +24,14 @@ class Icon extends NodeBase { this.resize(ctx); this.options.icon.size = this.options.icon.size || 50; - this.left = x - this.width * 0.5; - this.top = y - this.height * 0.5; + this.left = x - this.width / 2; + this.top = y - this.height / 2; this._icon(ctx, x, y, selected); if (this.options.label !== undefined) { var iconTextSpacing = 5; - this.labelModule.draw(ctx, x, y + this.height * 0.5 + iconTextSpacing, selected); + this.labelModule.draw(ctx, this.left + this.iconSize.width / 2 + this.margin.left, + y + this.height / 2 + iconTextSpacing, selected); } this.updateBoundingBox(x,y) diff --git a/lib/network/modules/components/nodes/shapes/Text.js b/lib/network/modules/components/nodes/shapes/Text.js index ac22dc5c..d2941d4a 100644 --- a/lib/network/modules/components/nodes/shapes/Text.js +++ b/lib/network/modules/components/nodes/shapes/Text.js @@ -5,14 +5,14 @@ import NodeBase from '../util/NodeBase' class Text extends NodeBase { constructor(options, body, labelModule) { super(options, body, labelModule); + this._setMargins(); } resize(ctx, selected) { if (this.width === undefined) { - var margin = 5; - var textSize = this.labelModule.getTextSize(ctx,selected); - this.width = textSize.width + 2 * margin; - this.height = textSize.height + 2 * margin; + this.textSize = this.labelModule.getTextSize(ctx,selected); + this.width = this.textSize.width + this.margin.right + this.margin.left; + this.height = this.textSize.height + this.margin.top + this.margin.bottom; this.radius = 0.5*this.width; } } @@ -24,7 +24,8 @@ class Text extends NodeBase { // draw shadow if enabled this.enableShadow(ctx); - this.labelModule.draw(ctx, x, y, selected || hover); + this.labelModule.draw(ctx, this.left + this.textSize.width / 2 + this.margin.left, + this.top + this.textSize.height / 2 + this.margin.top, selected || hover); // disable shadows for other elements. this.disableShadow(ctx); diff --git a/lib/network/modules/components/nodes/util/NodeBase.js b/lib/network/modules/components/nodes/util/NodeBase.js index 1cf6bf53..54956012 100644 --- a/lib/network/modules/components/nodes/util/NodeBase.js +++ b/lib/network/modules/components/nodes/util/NodeBase.js @@ -8,6 +8,7 @@ class NodeBase { this.height = undefined; this.width = undefined; this.radius = undefined; + this.margin = undefined; this.boundingBox = {top: 0, left: 0, right: 0, bottom: 0}; } @@ -15,6 +16,23 @@ class NodeBase { this.options = options; } + _setMargins() { + this.margin = {}; + if (this.options.margin) { + if (typeof this.options.margin == 'object') { + this.margin.top = this.options.margin.top; + this.margin.right = this.options.margin.right; + this.margin.bottom = this.options.margin.bottom; + this.margin.left = this.options.margin.left; + } else { + this.margin.top = this.options.margin; + this.margin.right = this.options.margin; + this.margin.bottom = this.options.margin; + this.margin.left = this.options.margin; + } + } + } + _distanceToBorder(ctx,angle) { var borderWidth = this.options.borderWidth; this.resize(ctx); @@ -70,4 +88,4 @@ class NodeBase { } } -export default NodeBase; \ No newline at end of file +export default NodeBase; diff --git a/lib/network/options.js b/lib/network/options.js index 2a5609b3..008685fe 100644 --- a/lib/network/options.js +++ b/lib/network/options.js @@ -197,6 +197,13 @@ let allOptions = { label: { string, 'undefined': 'undefined' }, labelHighlightBold: { boolean }, level: { number, 'undefined': 'undefined' }, + margin: { + top: { number }, + right: { number }, + bottom: { number }, + left: { number }, + __type__: { object, number } + }, mass: { number }, physics: { boolean }, scaling: {