vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

230 lines
5.4 KiB

/**
* Created by Alex on 3/4/2015.
*/
var util = require("../../util");
var DataSet = require('../../DataSet');
var DataView = require('../../DataView');
var Node = require("./components/nodes/NodeMain");
class NodesHandler {
constructor(body, images, groups, layoutEngine) {
this.body = body;
this.images = images;
this.groups = groups;
this.layoutEngine = layoutEngine;
// create the node API in the body container
this.body.functions.createNode = this.create.bind(this);
this.nodesListeners = {
'add': (event, params) => {this.add(params.items);},
'update': (event, params) => {this.update(params.items, params.data);},
'remove': (event, params) => {this.remove(params.items);}
};
this.options = {};
this.defaultOptions = {
mass: 1,
//radiusMin: 10,
//radiusMax: 30,
radius: 10,
scaling: {
min: 10,
max: 40,
label: {
enabled: true,
min: 14,
max: 30,
maxVisible: 30,
drawThreshold: 3
},
customScalingFunction: function (min,max,total,value) {
if (max == min) {
return 0.5;
}
else {
var scale = 1 / (max - min);
return Math.max(0,(value - min)*scale);
}
}
},
shape: 'ellipse',
image: undefined, // --> URL
//widthMin: 16, // px
//widthMax: 64, // px
label: undefined,
labelStyle: {
fontColor: 'black',
fontSize: 14, // px
fontFace: 'verdana',
fontFill: undefined,
fontStrokeWidth: 0, // px
fontStrokeColor: '#ffffff',
//scaleFontWithValue: false,
//fontSizeMin: 14,
//fontSizeMax: 30,
//fontSizeMaxVisible: 30,
//fontDrawThreshold: 3
},
value: 1,
color: {
border: '#2B7CE9',
background: '#97C2FC',
highlight: {
border: '#2B7CE9',
background: '#D2E5FF'
},
hover: {
border: '#2B7CE9',
background: '#D2E5FF'
}
},
group: undefined,
borderWidth: 1,
borderWidthSelected: undefined,
physics: true,
hidden: false,
icon: {
iconFontFace: undefined, //'FontAwesome',
code: undefined, //'\uf007',
iconSize: undefined, //50,
iconColor: undefined //'#aa00ff'
}
};
util.extend(this.options, this.defaultOptions);
}
setOptions(options) {
}
/**
* Set a data set with nodes for the network
* @param {Array | DataSet | DataView} nodes The data containing the nodes.
* @private
*/
setData(nodes) {
var oldNodesData = this.body.data.nodes;
if (nodes instanceof DataSet || nodes instanceof DataView) {
this.body.data.nodes = nodes;
}
else if (Array.isArray(nodes)) {
this.body.data.nodes = new DataSet();
this.body.data.nodes.add(nodes);
}
else if (!nodes) {
this.body.data.nodes = new DataSet();
}
else {
throw new TypeError('Array or DataSet expected');
}
if (oldNodesData) {
// unsubscribe from old dataset
util.forEach(this.nodesListeners, function (callback, event) {
oldNodesData.off(event, callback);
});
}
// remove drawn nodes
this.body.nodes = {};
if (this.body.data.nodes) {
// subscribe to new dataset
var me = this;
util.forEach(this.nodesListeners, function (callback, event) {
me.body.data.nodes.on(event, callback);
});
// draw all new nodes
var ids = this.body.data.nodes.getIds();
this.add(ids);
}
this.body.emitter.emit("_dataChanged");
}
/**
* Add nodes
* @param {Number[] | String[]} ids
* @private
*/
add(ids) {
var id;
var newNodes = [];
for (var i = 0; i < ids.length; i++) {
id = ids[i];
var data = this.body.data.nodes.get(id);
var node = new Node(data, this.images, this.groups, this.options);
newNodes.push(node);
this.body.nodes[id] = node; // note: this may replace an existing node
}
this.layoutEngine.positionInitially(newNodes);
this.body.emitter.emit("_dataChanged");
}
/**
* Update existing nodes, or create them when not yet existing
* @param {Number[] | String[]} ids
* @private
*/
update(ids, changedData) {
var nodes = this.body.nodes;
var dataChanged = false;
for (var i = 0; i < ids.length; i++) {
var id = ids[i];
var node = nodes[id];
var data = changedData[i];
if (node !== undefined) {
// update node
node.setOptions(data, this.constants);
}
else {
dataChanged = true;
// create node
node = new Node(properties, this.images, this.groups, this.constants);
nodes[id] = node;
}
}
if (dataChanged === true) {
this.body.emitter.emit("_dataChanged");
}
else {
this.body.emitter.emit("_dataUpdated");
}
}
/**
* Remove existing nodes. If nodes do not exist, the method will just ignore it.
* @param {Number[] | String[]} ids
* @private
*/
remove(ids) {
var nodes = this.body.nodes;
for (let i = 0; i < ids.length; i++) {
var id = ids[i];
delete nodes[id];
}
this.body.emitter.emit("_dataChanged");
}
create(properties) {
return new Node(properties, this.images, this.groups, this.options)
}
}
export default NodesHandler;