openwisp / netjsongraph.js

NetJSON NetworkGraph visualizer.
http://netjson.org
BSD 3-Clause "New" or "Revised" License
269 stars 78 forks source link
d3 mesh mesh-networks netjson network-graph network-topology networking wireless

netjsongraph.js

CI Coverage Status Language

img img img img

Leverage the power of EchartsJS and LeafletJS to visualize network topology using the NetJSON NetworkGraph format.

Build powerful and interoperable visualizations without losing flexibility!

Install and run demo examples

yarn install
yarn start

Arguments

netjsongraph.js accepts two arguments.

  1. url (required, string|array|object): URL(s) to fetch the JSON data from. It supports both NetJSON and GeoJSON data formats. You can also pass a NetJSON or GeoJSON object directly.

NetJSON format used internally is based on networkgraph but with a slight difference as follows:

{
    nodes: [{
        properties ? : {
            // Define node category
            category ? : String,

            /*
                Define the geographic coordinates of the node.
                Required when rendering a map.
            */
            location ? : {
                lng: Float,
                lat: Float,
            },

            // Define node updated time
            time ? : String
        }
    }],
    links: [{
        properties ? : {
            // Define link updated time
            time ? : String
        }
    }]
    flatNodes ? : {
        <node id>: node Object
    }
}
  1. options (optional, object): custom options described below

Configuration instructions

netjsongraph.js mainly relies on the Echarts for rendering, so the related configuration is mainly inherited from Echarts.

The library mainly supports two rendering modes -- graph and map. You can choose either of these and set it in render property in options.

In extreme cases, you can also pass your own render function if you don't want Echarts to render. We will pass in the processed netjson data and netjsongraph object.

For graph, you need to configure graphConfig property. We only support graph and graphGL. The main difference between graph and graphGL is the forceAtlas2 param series in Echarts. The latter is mainly used for big data rendering. You can use graphGL by setting graphConfig.type to graphGL. We use graph series and force layout by default. You can modify them freely according to the documentation.

For map, you need to configure mapOptions. The mapOptions and mapTileConfig are required for the map render. You can customize the nodes and links with nodeConfig and linkConfig optionally. For map nodes, you can also change the type to effectScatter series to enable animation effects.

You can also customize some global properties with echartsOption in echarts.

API Introduction

Core

Realtime Update

We use socket.io to monitor data changes which supports WebSockets and Polling. You can call JSONDataUpdate when the data change event occurs and pass the data to update the view.

/**
 * @function
 * @name JSONDataUpdate
 * Callback function executed when data update. Update Information and view.
 *
 * @param  {object|string}  Data     JSON data or url.
 * @param  {boolean}        override If old data need to be overrided? True defaultly. (Attention: Only 'map' render can set it `false`!)
 * @param  {boolean}        isRaw    If the data need to deal with the configuration? True defaultly.
 *
 * @this   {object}         NetJSONGraph object
 *
 */

const graph = new NetJSONGraph("./data/netjsonmap.json", {
    render: "graph",
});

graph.render();

const socket = io("http://localhost:3000/",{ transports : ['websocket'] });

socket.on("connect", function() {
    console.log("client connected");
});
socket.on("disconnect", function() {
    console.log("client disconnected");
});
// Self-monitoring server, re-render when the data changes.
socket.on("netjsonChange", graph.utils.JSONDataUpdate.bind(graph));

You can see this in action by executing the following commands:

cd examples/realtime_update

yarn install

yarn dev

In this demo the nodes and links change after 5 seconds.

Search elements

If you want to add search elements function, you just need to pass the url as param to searchElements, which will return a function searchFunc. Then you just need to obtain the value input, and pass it to the searchFunc. searchFunc is similar to JSONDataUpdate, you can also set appendData and isRaw params according to different conditions.

/**
 * @function
 * @name searchElements
 * Add search function for new data.
 *
 * @param  {string}         url      listen url
 *
 * @this   {object}         NetJSONGraph object
 *
 * @return {function}       searchFunc
 */

const graph = new NetJSONGraph("./data/netjsonmap.json", {
    onLoad: function(){
        let searchContainer = document.createElement("div"),
            searchInput = document.createElement("input"),
            searchBtn = document.createElement("button"),
            /*
                Pass in the url to listen to, and save the returned function.
                Please ensure that the return value of the api is the specified json format.
            */
            searchFunc = this.utils.searchElements.call(this, "https://ee3bdf59-d14c-4280-b514-52bd3dfc2c17.mock.pstmn.io/?search=");

        searchInput.setAttribute("class", "njg-searchInput");
        searchInput.placeholder = "Input value for searching special elements.";
        searchBtn.setAttribute("class", "njg-searchBtn");
        searchBtn.innerHTML = "search";
        searchContainer.setAttribute("class", "njg-searchContainer");
        searchContainer.appendChild(searchInput);
        searchContainer.appendChild(searchBtn);
        this.el.appendChild(searchContainer);

        searchInput.onchange = () => {
            // do something to deal user input value.
        };

        searchBtn.onclick = () => {
            let inputValue = searchInput.value.trim();

            /*
                Pass in the relevant search value,
                which will re-render automatically according to the request result within the function.
            */
            if(inputValue === "appendData"){
                // appendData
                searchFunc(inputValue, false);
            }
            else{
                searchFunc(inputValue);
            }

            searchInput.value = "";
        }

        this.utils.hideLoading();
    }
});

graph.render();

Demo is here. You can input test(overrideData) or appendData(appendData) and click the search button. The view will change if the value is valid, and you can also click the back button of browser to go back.

Deal data by WebWorker

You can deal with the data asynchronously by dealDataByWorker.

/**
 * @function
 * @name dealDataByWorker
 * Deal JSONData by WebWorker.
 *
 * @param  {object}    JSONData     NetJSONData
 * @param  {string}    workerFile   url
 * @param  {function}  callback     override data and render defaultly.
 *
 * @this   {object}    _this        NetJSONGraph object
 *
 */

Demo is here. You can simply set the dealDataByWorker param in config to process the data asynchronously before rendering. Of course you can also call the function directly.

DateParse

We provide a function -- dataParse for parsing the time field. We mainly use it to parse the time into the browser's current time zone based on the incoming matching rules.

/**
 * @function
 * @name dateParse
 *
 * Parse the time in the browser's current time zone based on the incoming matching rules.
 * The exec result must be [date, year, month, day, hour, minute, second, millisecond?]
 *
 * @param  {string}          dateString    "2000-12-31T23:59:59.999Z"
 * @param  {object(RegExp)}  parseRegular  /^([1-9]\d{3})-(\d{1,2})-(\d{1,2})T(\d{1,2}):(\d{1,2}):(\d{1,2})(?:\.(\d{1,3}))?Z$/ defaultly
 * @param  {number}          hourDiffer    you can custom time difference, default is the standard time difference

*
* @return {string}    Date string
*/

If you provide time field in node or link's properties, it'll display the parse date in the detail info defaultly.

Demo is here.

Load more data using geographic extent

You can load more data from the server even when the total number of nodes are greater than maxPointsFetched using geographic extent. You can specify the zoom level at which more data is loaded by setting loadMoreDataZoomLevel in the config.

You can see this in action by executing the following commands:

cd examples/load_data_geo_extent

yarn install

yarn start

Render

Utils

Example Usage

<!DOCTYPE html>
<html lang="en">
<head>
    <title>netjsongraph.js: basic example</title>
    <meta charset="utf-8">
    <!-- theme can be easily customized via css -->
    <link href="https://github.com/openwisp/netjsongraph.js/blob/master/./src/css/netjsongraph-theme.css" rel="stylesheet">
    <link href="https://github.com/openwisp/netjsongraph.js/blob/master/./src/css/netjsongraph.css" rel="stylesheet">
</head>
<body>
    <script type="text/javascript" src="https://github.com/openwisp/netjsongraph.js/raw/master/./dist/netjsongraph.min.js"></script>
    <script type="text/javascript">
        const graph = new NetJSONGraph("../src/data/netjson.json", {
            render: "graph",
        });
        graph.render();
    </script>
</body>
</html>

Example Demos

The demo shows default graph render.
Basic graph demo

The demo shows map render.
Map demo

The demo shows how to use graphGL to render big data.
graphGL(bigData) demo

The demo shows how to set custom attributes.
Custom attributes demo

The demo shows the multiple links render.
Currently only supports up to two links.
Multiple links demo

The demo is used to show how to deal with the multiple interfaces in the NetJSON data. We provide a work file to process the data before rendering.
This file provides functions to remove dirty data, deduplicate, handle multiple interfaces, add node links, add flatNodes and so on.
You can also define related files yourself.
Multiple interfaces demo

The demo is used to show the use of the dateParse function.
You can set the node or link property value time, we will call this function to parse the string in the element details defaultly.
Of course you can also call directly.
dateParse demo

The demo shows how to switch the netjsongraph render mode -- svg or canvas.
Switch render mode demo

The demo shows how to switch the netjsongraph render mode -- graph or map.
Switch graph mode demo

The demo is used to show the use of the searchElements function.
For test, you can input test or appendData and click the search button.
Search elements demo

The demo shows how to interact with elements.
Nodes expand or fold demo

The demo is used to show how to use the JSONDataUpdate function to update data.
See other examples:
netjson-updateData.html: It chooses override data.
netjsonmap-appendData.html: It chooses append data.
JSONDataUpdate using override option demo

The demo shows hwo to set path animation.
Geographic map animated links demo

The demo is used to show how to set indoor map.
Mainly the operation of leaflet.
Indoor map demo

The demo is used to show how to use the leaflet plugins.
Mainly the operation of leaflet.
Leaflet plugins demo

The demo shows the multiple tiles render.
Map with multiple tiles demo

The demo is used to show how to use the JSONDataUpdate function to update data.
Here we choose to append data by modify the default parameter.
See other examples:
netjson-updateData.html: It chooses override data.
netjsonmap-nodeTiles.html: override data by different zoom value.
JSONDataUpdate using append option demo

Using array files to append data step by step at start.
Similiar to the first method, but easier.
Append data using arrays demo

The demo shows the clustering of nodes.
Clustering demo

Upgrading from 0.1.x versions to 0.2.x

We advise all users of netjsongraph.js who are using the 0.1.x version to upgrade to the latest version.

The following steps explain how to upgrade.

  1. Download the latest version of netjsongraph.js
  2. Replace the old version of netjsongraph.min.js with the new version
  3. Replace the old version of netjsongraph-theme.css with the new version
  4. Replace the old version of netjsongraph.css with the new version
  5. Replace the deprecated options with the equivalent new options. See the Arguments section for more details.

The following list shows the deprecated options:

The function definition for onInit and onLoad has been changed: passing any additional arguments to these functions is not needed anymore.

The option linkDistance has been renamed to edgeLength. Options like edgeLength, friction, gravity are now passed as an object named force in series property of graphConfig. Learn more about graphConfig by looking at the Arguments section. Refer to the Echarts documentation for more details.

Use label instead of labelDx and labelDy in the series property of graphConfig. Refer to the Arguments section for more details. You can learn more about label in the Echarts documentation.

Use onClickElement instead of onClickNode and onClickLink. Refer to the Arguments section section for more details.

Contributing

  1. Fork it!
  2. Create your feature branch: git checkout -b my-new-feature
  3. Commit your changes: git commit -am 'Add some feature'
  4. Push to the branch: git push origin my-new-feature
  5. Submit a pull request :D

License

BSD 3-Clause License.