我编写了一个搜索函数来运行一个可能相当大的d3树,并且只过滤出匹配搜索模式的节点。
该搜索功能工作良好,速度也相当快。
但是,由于服务器上的数据量和计算数据的时间,如果用户清除搜索或输入另一个搜索,而不进行另一个查询,我希望能够将树重置为其初始内容。这不管用。
,这就是我尝试过的:
1-克隆d3节点
首先,我看了一下,他们有几个建议。从茉莉花身上跑出来,我的克隆技术似乎奏效了(不知道为什么)。
在我的应用程序中运行代码,我会得到一个即时的错误。准确的错误取决于我使用的代码- jquery.extend或JSON.parse of JSON.stringify。
我怀疑这是因为每个节点d都有一个d.parent属性和一个d.children属性,所以只要您想递归地克隆它的子节点,它就会进入一个循环。
2-设置d3.layout.tree.children以过滤数据。
然后我注意到有一个d3.layout.tree.children函数,我可以用它来操作树。因此,我这样做而不是复制json数据,并且只返回d.visible为真的节点。我的想法是,我不需要做任何事,当我想要重置,我只是回到基地,不过滤,孩子们。
这也不起作用--不匹配搜索的子节点现在已经从数据中消失了,而不仅仅是图表。
更新:我删除了我的初始示例代码,它没有工作,我自己给出了一个对我有用的初步答案.
发布于 2015-03-25 17:19:09
不确定这是否是最优雅的方法,但它对我有效。
基本上,在进行搜索之前,我只需将引用复制到现有的_nodes。搜索通过匹配搜索模式的树和克隆节点进行递归。以及具有匹配搜索模式的子节点的任何节点。因此克隆体的体积受匹配量的限制。克隆代码本身是相当天真的-它只处理原始值,但这是我现在所需要的。
注意:_nodes基本上是您在任何在线d3示例中看到的传入json数据。
//support an array of possible attributes for string matches...
var li_tosearch = ["label"];
//a "set" of node attributes that should not be copied
s_skip = Object.create(null);
s_skip.parent = 1;
s_skip.children = 1;
s_skip._children = 1;
s_skip._unfiltered_children = 1;
function clone_n_filter(pattern, d) {
/* recursive search by node
- a node is visible if one of its searchable attributes
matches the pattern or if one of its children/_children is
visible.
- only visible nodes get cloned
*/
if (!d || !pattern){
return;
}
var visible_child, clone, v, s;
var visible = false;
//support an array of possible attributes for string matches...
for (var i = 0; i < li_tosearch.length; ++i){
s = d[li_tosearch[i]];
if (s){
if (s.match(pattern)){
visible = true;
break;
}
}
}
var children = [], _children = [];
//if any of the children are visible then the current is visible too
if (d.children) {
for (var index = 0; index < d.children.length; ++index) {
visible_child = clone_n_filter(pattern, d.children[index]);
if (visible_child) {
children.push(visible_child);
visible = true;
}
}
}
if (d._children) {
for (var index2 = 0; index2 < d._children.length; ++index2) {
visible_child = clone_n_filter(pattern, d._children[index2]);
if (visible_child) {
_children.push(visible_child);
visible = true;
}
}
}
//not being used, but keeps track of all original children
//this is just a reference, so memory cost is low
//possible use case: expand a non-leaf node that has
//no visible children
d._unfiltered_children = d.children || d._children;
if (visible){
clone = d.constructor(); // changed
for(var key in d) {
if (key in s_skip){
continue;
}
if(d.hasOwnProperty(key)) {
v = d[key];
//given the domain, only expecting primitives...
//will address when that breaks
if (typeof(v) === 'object'){
throw("unexpected complex object:[" + typeof(v) + " " + key + "]");
}
clone[key] = v;
}
else{
//keeping track of attributes we won't be copying
s_skip[key] = 1;
}
}
clone.children = children;
clone._children = _children;
}
return clone;
}整件事的入口点。重置非常快-它只是将_nodes设置为原始保存的引用。
_chart.search = function(pattern){
/* external entry point for calling the search*/
if (!_nodes){
return;
}
if (!pattern){
//no search pattern
if (_o_nodes){
//restore unfiltered
_nodes = _o_nodes;
}
chart.render();
return;
}
if (!_o_nodes){
//no need to clone the _nodes, just copy reference
_o_nodes = _nodes;
}
var patre = new RegExp(pattern,"gi");
_nodes = clone_n_filter(patre, _o_nodes);
chart.render();
};https://stackoverflow.com/questions/29221075
复制相似问题