渲染图后节点属性的异步更新 (Vivagraph.js)
Asynchronous update of nodes properties after the graph is rendered (Vivagraph.js)
我正在尝试异步填充图表中的节点数据。
如何确保异步获取的数据实际绑定到图形,并在准备就绪时呈现?
首先,您渲染图形结构、节点和链接。
其次,当数据准备好时,您将数据呈现为节点的属性。
新节点可以通过父节点交互动态添加,不需要等待节点属性完成。
请注意,我正在使用 Vivagraph.js 库。graph
是使用该库创建的对象,addLinks()
和 getNode()
是其函数属性 - 请参阅演示Vivagraph demo,我将其用作尝试的草稿。
我遇到的问题是节点一添加就在图中呈现 - addNode() addLinks(node1, node2) 函数 -,同时异步获取节点的属性 - getNode(node).属性 = updatedValue - 结果 undefined.
已编辑 - 基于评论的简化代码
下面我提供了一个工作模型版本,它基于这个(很棒的)库的作者 @Anvaka 提供的教程。
我的目标 是立即呈现图形,启用交互,并在从第三方获取数据时更新数据。
// attempt 1: fetch data async
var fetchInfo = function (graph, nodeId) {
var root = 'http://jsonplaceholder.typicode.com';
$.ajax({
url: root + '/photos/' + nodeId,
method: 'GET'
}).then(function (data) {
graph.getNode(nodeId).data = data.thumbnailUrl;
console.log(graph.getNode(nodeId));
});
};
// attempt 2: defer ajax directly
var fetchInfo_2 = function (graph, nodeId) {
var root = 'http://jsonplaceholder.typicode.com';
return $.ajax({
url: root + '/photos/' + nodeId,
method: 'GET'
});
};
function main() {
// As in previous steps, we create a basic structure of a graph:
var graph = Viva.Graph.graph();
graph.addLink(1, 2);
fetchInfo(graph, 1); // updated data is undefined when graph is rendered
fetchInfo(graph, 2); // updated data is undefined when graph is rendered
/* trying a different outcome by deferring whole ajax
graph.getNode(1).data = fetchInfo_2(1).done(function(data) {
data.thumbnailUrl;
}); // the whole object is deferred but cannot fetch data
graph.getNode(2).data = fetchInfo_2(2).done(function(data) {
data.thumbnailUrl;
}); // the whole object is deferred but cannot fetch data
*/
var graphics = Viva.Graph.View.svgGraphics(),
nodeSize = 24,
addRelatedNodes = function (nodeId, isOn) {
for (var i = 0; i < 6; ++i) {
var child = Math.floor((Math.random() * 150) + nodeId);
// I add children and update data from external sources
graph.addLink(nodeId, child);
fetchInfo(graph, child);
}
};
// dynamically add nodes on mouse interaction
graphics.node(function (node) {
var ui = Viva.Graph.svg('image')
.attr('width', nodeSize)
.attr('height', nodeSize)
.link(node.data);
console.log('rendered', node.id, node.data);
$(ui).hover(function () {
// nodes are rendered; nodes' data is undefined
addRelatedNodes(node.id);
});
return ui;
}).placeNode(function (nodeUI, pos) {
nodeUI.attr('x', pos.x - nodeSize / 2).attr('y', pos.y - nodeSize / 2);
});
graphics.link(function (link) {
return Viva.Graph.svg('path')
.attr('stroke', 'gray');
}).placeLink(function (linkUI, fromPos, toPos) {
var data = 'M' + fromPos.x + ',' + fromPos.y +
'L' + toPos.x + ',' + toPos.y;
linkUI.attr("d", data);
})
var renderer = Viva.Graph.View.renderer(graph, {
graphics: graphics
});
renderer.run();
}
main();
svg {
width: 100%;
height: 100%;
}
<script src="https://rawgit.com/anvaka/VivaGraphJS/master/dist/vivagraph.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
正如我在评论中所说的那样,您想要作为异步过程的结果执行的任何工作都必须在回调中完成。这包括任何渲染工作。
对于 jQuery 的延迟(如 Ajax 调用的结果),回调是通过 .then
或 .done
定义的,使您能够分离从使用资源中获取资源的行为。
设置图片源属于渲染工作,必须在回调中进行。下面是一个获取图像和 returns 延迟结果的函数,node
回调函数使用它来完成自己的工作。
function fetchInfo(id) {
var root = 'http://jsonplaceholder.typicode.com';
return $.getJSON(root + '/photos/' + id);
}
function main() {
var graph = Viva.Graph.graph(),
graphics = Viva.Graph.View.svgGraphics(),
nodeSize = 24,
addRelatedNodes = function (nodeId, count) {
var childId, i;
for (i = 0; i < count; ++i) {
childId = Math.floor(Math.random() * 150) + nodeId;
graph.addLink(nodeId, childId);
}
};
graphics
.node(function (node) {
var ui = Viva.Graph.svg('image')
.attr('width', nodeSize)
.attr('height', nodeSize)
.link('http://www.ajaxload.info/images/exemples/24.gif');
$(ui).dblclick(function () {
addRelatedNodes(node.id, 6);
});
// render when ready
fetchInfo(node.id).done(function (data) {
ui.link(data.thumbnailUrl);
});
return ui;
})
.placeNode(function (nodeUI, pos) {
nodeUI.attr('x', pos.x - nodeSize / 2).attr('y', pos.y - nodeSize / 2);
})
.link(function (link) {
return Viva.Graph.svg('path')
.attr('stroke', 'gray');
})
.placeLink(function (linkUI, fromPos, toPos) {
var data =
'M' + fromPos.x + ',' + fromPos.y +
'L' + toPos.x + ',' + toPos.y;
linkUI.attr("d", data);
});
graph.addLink(1, 2);
Viva.Graph.View.renderer(graph, {
graphics: graphics
}).run();
}
main();
svg {
width: 100%;
height: 100%;
}
img {
cursor: pointer;
}
<script src="https://rawgit.com/anvaka/VivaGraphJS/master/dist/vivagraph.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
遗憾的是,它在 StackSnippets 中似乎没有 运行,但它在 jsFiddle 上有效:http://jsfiddle.net/tL9992ua/
我正在尝试异步填充图表中的节点数据。
如何确保异步获取的数据实际绑定到图形,并在准备就绪时呈现?
首先,您渲染图形结构、节点和链接。 其次,当数据准备好时,您将数据呈现为节点的属性。 新节点可以通过父节点交互动态添加,不需要等待节点属性完成。
请注意,我正在使用 Vivagraph.js 库。graph
是使用该库创建的对象,addLinks()
和 getNode()
是其函数属性 - 请参阅演示Vivagraph demo,我将其用作尝试的草稿。
我遇到的问题是节点一添加就在图中呈现 - addNode() addLinks(node1, node2) 函数 -,同时异步获取节点的属性 - getNode(node).属性 = updatedValue - 结果 undefined.
已编辑 - 基于评论的简化代码
下面我提供了一个工作模型版本,它基于这个(很棒的)库的作者 @Anvaka 提供的教程。
我的目标 是立即呈现图形,启用交互,并在从第三方获取数据时更新数据。
// attempt 1: fetch data async
var fetchInfo = function (graph, nodeId) {
var root = 'http://jsonplaceholder.typicode.com';
$.ajax({
url: root + '/photos/' + nodeId,
method: 'GET'
}).then(function (data) {
graph.getNode(nodeId).data = data.thumbnailUrl;
console.log(graph.getNode(nodeId));
});
};
// attempt 2: defer ajax directly
var fetchInfo_2 = function (graph, nodeId) {
var root = 'http://jsonplaceholder.typicode.com';
return $.ajax({
url: root + '/photos/' + nodeId,
method: 'GET'
});
};
function main() {
// As in previous steps, we create a basic structure of a graph:
var graph = Viva.Graph.graph();
graph.addLink(1, 2);
fetchInfo(graph, 1); // updated data is undefined when graph is rendered
fetchInfo(graph, 2); // updated data is undefined when graph is rendered
/* trying a different outcome by deferring whole ajax
graph.getNode(1).data = fetchInfo_2(1).done(function(data) {
data.thumbnailUrl;
}); // the whole object is deferred but cannot fetch data
graph.getNode(2).data = fetchInfo_2(2).done(function(data) {
data.thumbnailUrl;
}); // the whole object is deferred but cannot fetch data
*/
var graphics = Viva.Graph.View.svgGraphics(),
nodeSize = 24,
addRelatedNodes = function (nodeId, isOn) {
for (var i = 0; i < 6; ++i) {
var child = Math.floor((Math.random() * 150) + nodeId);
// I add children and update data from external sources
graph.addLink(nodeId, child);
fetchInfo(graph, child);
}
};
// dynamically add nodes on mouse interaction
graphics.node(function (node) {
var ui = Viva.Graph.svg('image')
.attr('width', nodeSize)
.attr('height', nodeSize)
.link(node.data);
console.log('rendered', node.id, node.data);
$(ui).hover(function () {
// nodes are rendered; nodes' data is undefined
addRelatedNodes(node.id);
});
return ui;
}).placeNode(function (nodeUI, pos) {
nodeUI.attr('x', pos.x - nodeSize / 2).attr('y', pos.y - nodeSize / 2);
});
graphics.link(function (link) {
return Viva.Graph.svg('path')
.attr('stroke', 'gray');
}).placeLink(function (linkUI, fromPos, toPos) {
var data = 'M' + fromPos.x + ',' + fromPos.y +
'L' + toPos.x + ',' + toPos.y;
linkUI.attr("d", data);
})
var renderer = Viva.Graph.View.renderer(graph, {
graphics: graphics
});
renderer.run();
}
main();
svg {
width: 100%;
height: 100%;
}
<script src="https://rawgit.com/anvaka/VivaGraphJS/master/dist/vivagraph.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
正如我在评论中所说的那样,您想要作为异步过程的结果执行的任何工作都必须在回调中完成。这包括任何渲染工作。
对于 jQuery 的延迟(如 Ajax 调用的结果),回调是通过 .then
或 .done
定义的,使您能够分离从使用资源中获取资源的行为。
设置图片源属于渲染工作,必须在回调中进行。下面是一个获取图像和 returns 延迟结果的函数,node
回调函数使用它来完成自己的工作。
function fetchInfo(id) {
var root = 'http://jsonplaceholder.typicode.com';
return $.getJSON(root + '/photos/' + id);
}
function main() {
var graph = Viva.Graph.graph(),
graphics = Viva.Graph.View.svgGraphics(),
nodeSize = 24,
addRelatedNodes = function (nodeId, count) {
var childId, i;
for (i = 0; i < count; ++i) {
childId = Math.floor(Math.random() * 150) + nodeId;
graph.addLink(nodeId, childId);
}
};
graphics
.node(function (node) {
var ui = Viva.Graph.svg('image')
.attr('width', nodeSize)
.attr('height', nodeSize)
.link('http://www.ajaxload.info/images/exemples/24.gif');
$(ui).dblclick(function () {
addRelatedNodes(node.id, 6);
});
// render when ready
fetchInfo(node.id).done(function (data) {
ui.link(data.thumbnailUrl);
});
return ui;
})
.placeNode(function (nodeUI, pos) {
nodeUI.attr('x', pos.x - nodeSize / 2).attr('y', pos.y - nodeSize / 2);
})
.link(function (link) {
return Viva.Graph.svg('path')
.attr('stroke', 'gray');
})
.placeLink(function (linkUI, fromPos, toPos) {
var data =
'M' + fromPos.x + ',' + fromPos.y +
'L' + toPos.x + ',' + toPos.y;
linkUI.attr("d", data);
});
graph.addLink(1, 2);
Viva.Graph.View.renderer(graph, {
graphics: graphics
}).run();
}
main();
svg {
width: 100%;
height: 100%;
}
img {
cursor: pointer;
}
<script src="https://rawgit.com/anvaka/VivaGraphJS/master/dist/vivagraph.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
遗憾的是,它在 StackSnippets 中似乎没有 运行,但它在 jsFiddle 上有效:http://jsfiddle.net/tL9992ua/