2014-02-13 36 views
0

我有一个小程序使用RaphaelJS来接受一些节点和边,很像arborjs和sigmajs来生成树形图。我会使用上述两个库中的任何一个,但我正在尝试学习一些JS和图论,并且我想为什么不自己尝试类似的东西。JS通过迭代指定回调

节点迭代并放置在纸上,并给出回调函数悬停和悬停。将鼠标悬停在悬停的动画部分可以工作,但弹出文本显示的是分配时迭代的最后一个值。

我发现这是因为我需要使用闭包,但是我试图在我发现的几个不同的例子之后编写闭包。提前link

var jgraph = { 
obj_nodes : [], 
obj_edges : [], 
addNodes : function(obj) { 
    this.obj_nodes[obj.id] = obj; 
}, 
getNodes : function() { 
    return this.obj_nodes; 
}, 
addEdges : function(obj) { 
    this.obj_edges[obj.id] = obj; 
}, 
getEdges : function() { 
    return this.obj_edges; 
}, 
createGraph : function(paper, obj) { 
    var point_x, point_y, 
    source_x, source_y, target_x, target_y, popup; 
    for (var i = 0; i < obj.nodes.length; i++) { 
     this.obj_nodes[obj.nodes[i].id] = obj.nodes[i], 
     point_x = this.obj_nodes[obj.nodes[i].id].x, 
     point_y = this.obj_nodes[obj.nodes[i].id].y; 
     popup = jgraph.createPopup(paper, obj.nodes[i].id); 
     paper.circle(point_x, point_y, 10).attr({ 
       fill : "#e74c3c", 
       stroke : "none" 
      }).hover(function() { 
       this.animate({ 
        fill : "#3498db", 
        transform : "s1.5" 
       }, 900, "elastic"); 
       popup.show().toFront(); 
      }, function() { 
       this.animate({ 
        fill : "#e74c3c", 
        transform : "s1" 
       }, 900, "elastic"); 
       popup.hide(); 
     }); 
    } 
    for (var i = 0; i < obj.edges.length; i++) { 
     this.obj_edges[obj.edges[i].id] = obj.edges[i]; 
     source_x = this.obj_nodes[obj.edges[i].source].x, 
     source_y = this.obj_nodes[obj.edges[i].source].y, 
     target_x = this.obj_nodes[obj.edges[i].target].x, 
     target_y = this.obj_nodes[obj.edges[i].target].y; 
     p.path("M " + source_x + " " + source_y + " L " + target_x + " " + target_y).toBack().attr({ 
      stroke : "#e74c3c", 
      "stroke-width" : 4 
     }); 
    } 
}, 
createPopup : function(paper, id) { 
    return paper.text(this.obj_nodes[id].x, this.obj_nodes[id].y - 20, this.obj_nodes[id].label).hide().attr({ 
     "font-size" : "13px" 
    }); 
} 
}; 

感谢:

我已经发布了一个例子上的jsfiddle!

回答

1

关闭可以肯定是令人发狂。在这种情况下,问题在于您在for循环的上下文中安装悬停处理程序,并且该闭包将处理程序对popup的引用绑定到for循环上下文外定义的变量。自然,在悬停处理程序启动时,for循环已完成执行,并且popup的值反映了循环处理的最后一个标签。

试试这个 - 你基本上只是声明了一个匿名函数你在for循环和传递的popup每个值到该功能,这使得封闭绑定到该匿名函数调用特定的值:

 popup = jgraph.createPopup(paper, obj.nodes[i].id); 
     (function(popup) 
      {    
      paper.circle(point_x, point_y, 10).attr({ 
        fill : "#e74c3c", 
        stroke : "none" 
       }).hover(function() { 
        this.animate({ 
         fill : "#3498db", 
         transform : "s1.5" 
        }, 900, "elastic"); 
        popup.show().toFront(); 
       }, function() { 
        this.animate({ 
         fill : "#e74c3c", 
         transform : "s1" 
        }, 900, "elastic"); 
        popup.hide(); 
      }); 
      })(popup); 

如果我是你,我可能会使用Raphael元素的data方法将标签分配给每个元素,然后分别在每次悬停开始和结束时创建并销毁文本元素。这样你根本不用担心管理许多隐形元素=)

这是你的fiddle in working condition的一个分支。

+0

谢谢!实际上我曾尝试过类似的东西,但是我在anom函数中使用了createGraph(),并且将obj.nodes [i] .id传递给了anom函数。再次感谢您的示例,解释和建议! – matak