Search code examples
javascriptvis.js

How to define a custom default style (preset) for dynamic groups in a vis.js network without manually assigning colors to a group or to a node


I use vis.js network to visualize the network connections. The json data can be loaded dynamically. So the names of groups and nodes can change. Therefore, it is not possible to define colors for each group individually in a static style to groupname mapping. Reading the docs I could only find how to set group color by name individually by group.

I have tested about 30 Groups and some of the default styles had bad contrast and the text is barely visible (black on darkblue).

bad coloring

How I think it should be implemented - shortened example with only blue and font color change if too bright -:

var options = {
  groups: {
    defaultstyles: [
        0: {color:{background: '#03045E'}, borderWidth:3, font: {color: '#ffffff'}},
        1: {color:{background: '#0077B6'}, borderWidth:3, font: {color: '#ffffff'}},
        2: {color:{background: '#00B4D8'}, borderWidth:3, font: {color: '#000000'}},
        3: {color:{background: '#90E0EF'}, borderWidth:3, font: {color: '#000000'}},
        n: {color:{background: '#CAF0F8'}, borderWidth:3, font: {color: '#000000'}}
    ]
  }
}

The defaultstyles just shows what I expect to find, but it isn't a valid option at the moment.

The documented "useDefaultGroups: true" is what I want but with different colors. I checked the JS file and found this._defaultGroups. Although I could change the values in a copy of the JS file, it seems to be wrong and may cause problems when trying to update the JS file after some time.


Solution

  • var options = {
      groups: {
        // step 1. define your default group styles by usual group ways,
        //         but with special prefix `d`, or any rules you like
        d0: {color:{background: '#03045E'}, borderWidth:3, font: {color: '#ffffff'}},
        d1: {color:{background: '#0077B6'}, borderWidth:3, font: {color: '#ffffff'}},
        d2: {color:{background: '#00B4D8'}, borderWidth:3, font: {color: '#000000'}},
        d3: {color:{background: '#90E0EF'}, borderWidth:3, font: {color: '#000000'}},
        // ...
        dn: {color:{background: '#CAF0F8'}, borderWidth:3, font: {color: '#000000'}}
      }
    }
    
    var loadedNodes = [
        {id:1, group: 'myGroup', label:"I'm in a custom group called 'myGroup'!"},
        {id:2, val: 1, label:"I have no group name!"},
        {id:3, val: 2, label:"I have no group name!"},
    ]
    // step 2. assign a default group name to them
    for (let node of loadedNodes) {
        assignGroupNameIfNeed(node)
    }
    
    function assignGroupNameIfNeed(node) {
        // do nothing if it already has `group`
        if (node.group) return
    
        node.group = 'd' + node.id
        // or node.group = 'd' + node.value, which is based on node value
        // you can implement any mapping logic here
    }