VISJS:将操纵数据保存到json

时间:2016-11-08 14:40:20

标签: javascript vis.js vis.js-network

我正在使用vis.js在网页上创建网络图。

我需要将操纵的图形以JSON格式存储到数据库,从网络图中导出json。

我没有找到任何关于它的文档,是否可以将带有操纵数据的vis.js网络导出(以JSON或可转换为JSON的形式)?

3 个答案:

答案 0 :(得分:0)

根据Visjs文档,您可能需要的方法是 storePositions()

这是功能描述:

  

使用vis.DataSet将节点加载到网络中时,此方法会将所有节点的X和Y位置放入该数据集中。如果您从数据库加载节点并使其与DataSet动态耦合,您可以使用它来稳定您的网络一次,然后通过DataSet保存该数据库中的位置,以便下次加载节点时,稳定将接近瞬间。

     

如果节点仍在移动,并且您正在使用动态平滑边缘   (默认情况下已启用),您可以使用该选项   物理模块中的stabilization.onlyDynamicEdges改进   初始化时间。

     

此方法不支持群集。目前,在使用群集时无法缓存位置,因为无法从位置正确初始化位置。

VisJs docs

答案 1 :(得分:0)

对于数据,这是我提取数据进行存储的方法(我将尝试切断与该问题无关的代码位):

// get nodes and edges
var nodes = network.body.data.nodes._data; // contains id, label, x,y, custom per-node options and doesn't contain options from options.nodes; presumably contains option values set when network was created, not current ones (it is so for x,y)
// network.body.nodes[id].nodeOptions shows options from options.nodes but not custom per-node options (same for edges and network.body.edges[id].edgeOptions)
// network.body.nodes contain much more stuff (x,y, default stuff)
//# look for a suitable getter
var edges = network.body.data.edges._data; // map; for edges to/from? certain node use network.getConnectedNodes(id)
// network.body.data.edges._data is a hash of { id: , from: , to: }

// get node positions
var positions = network.getPositions(),
    nodeIds = Object.keys(nodes);

// get data describing nodes, edges and options for storage
var storedEdges = [], storedEdge, storedNodes = [], storedNode;
var indexIds = {}, idIndex = 1, end;

for(var nodeId in nodes) {
    // nodes[nodeId].x is the initial value, positions[nodeId].x is the current one
    if(positions[nodeId]) { // undefined for hidden
        nodes[nodeId].x = positions[nodeId].x;
        nodes[nodeId].y = positions[nodeId].y;
    }
    storedNode = copyObjectProperties(nodes[nodeId]);

    // don't store id unless that breaks connected edges
    if(!network.getConnectedEdges(nodeId).length)
        storedNode.id = undefined;
    // substitute generated ids with no semantics with simple indices
    if(/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/.exec(storedNode.id)) {

        while(nodes[idIndex])
            idIndex++;
        indexIds[storedNode.id] = idIndex; // remember the given index
        storedNode.id = idIndex; // substitute with an index
        idIndex++;
    }

    storedNodes.push(storedNode);
}
for(var edgeId in edges) {
    storedEdge = copyObjectProperties(edges[edgeId]);
    storedEdge.id = undefined; // then strip id

    // change from/to in accord to the substitution above (for nodes' ids)
    for(end of ["from","to"])
        storedEdge[end] = indexIds[storedEdge[end]] || storedEdge[end];

    storedEdges.push(storedEdge);
}

dataAndOptions = {
    data: { nodes: storedNodes, edges: storedEdges },
    options: storedOptions
};

var dataAndOptionsText = JSON.stringify(dataAndOptions,"",4)
    .replace(/ {4}/gm,"\t").replace(/},\n\t\t\t{/gm,"},{");

和帮助程序定义:

// helper for storing options
var copyObjectProperties = function(obj) {
    return JSON.parse(JSON.stringify(obj));
};

有关更多上下文,请参阅my plugin以获取TiddlyWiki Classic(saveDataAndOptions方法)。它不是最新版本,但我会在某个时候进行更新。

关于网络选项(如果已更改),我haven't figured还是不错的方法。

答案 2 :(得分:0)

tl; dr

使用storePositions()将X和Y坐标加载到数据集中。您可以对其进行序列化,然后在稍后初始化网络时使用序列化的坐标扩展节点。

说明

vis.js Network docs on storePositions()说:

使用vis.DataSet将节点加载到网络时,此方法会将所有节点的X和Y位置放入该数据集中。如果您要从数据库加载节点并使其与数据集动态耦合,则可以使用它来稳定网络一次,然后通过数据集将位置保存在该数据库中,以便下次加载节点时,稳定化将接近瞬间。

保存

您必须为network.data使用vis.js的DataSet。要“保存”,只需调用network.storePositions(),以便它可以将X和Y坐标加载到network.data.nodes,然后按需要对其进行序列化。

正在加载

您只需forEach()您的network.data.nodes并通过update()将序列化的X和Y坐标添加到其节点。

示例

在此演示中,位置被序列化为textarea。您可以生成随机放置的图(这是默认行为),移动节点,对其进行序列化,可以选择在textarea中对其进行编辑,然后将其加载回去。

const nodes = [
  { id: 1, label: 1 },
  { id: 2, label: 2 },
  { id: 3, label: 3 },
  { id: 4, label: 4 },
]

const edges = [
  { id: '1-2',  from: 1, to: 2 },
  { id: '1-3', from: 1, to: 3 },
  { id: '2-3', from: 2, to: 3 },
  { id: '1-4', from: 1, to: 4 },
]

const positionsElement = document.getElementById('positions')
const container = document.getElementById('graph')
const data = {
  nodes: new vis.DataSet(nodes),
  edges: new vis.DataSet(edges),
}
const options = {
  layout: {
    improvedLayout: false,
  },
  edges: {
    smooth: false,
  },
  physics: false,
}

let network = null

function initGraph(generateRandomPosition = true) {
  if (generateRandomPosition) {
    data.nodes.forEach(node => {
      data.nodes.update({ id: node.id, x: undefined, x: undefined })
    })
  }
  network = new vis.Network(container, data, options)
}

document.getElementById('generate-graph').addEventListener('click', initGraph)

document.getElementById('extract-positions').addEventListener('click', e => {
  network.storePositions()
  const nodePositions = data.nodes.map(({ id, x, y }) => ({ id, x, y }))
  positionsElement.value = JSON.stringify(nodePositions)
})

document.getElementById('load-positions').addEventListener('click', e => {
  const nodePositions = JSON.parse(positionsElement.value)
  nodePositions.forEach(nodePosition => data.nodes.update(nodePosition))
  initGraph(false)
})
#graph {
  width: 100%;
  height: 300px;
  border: 1px solid lightgray;
}

#positions {
  width: 100%;
  min-height: 60px;
}
<link href="https://visjs.github.io/vis-network/dist/vis-network.min.css" rel="stylesheet" />
<script src="https://visjs.github.io/vis-network/dist/vis-network.min.js"></script>
<div id="graph"></div>
<button id="generate-graph">Generate graph</button>
<button id="extract-positions">Extract positions</button>
<button id="load-positions">Load positions</button>
<textarea id="positions"></textarea>