Protovis Treemap - 悬停时显示标签

时间:2011-09-21 19:06:10

标签: javascript treemap protovis

我有一个我创建的树形图。现在我正试图让悬停过度正常工作。我希望每个treemap.leaf的文本仅在用户将鼠标悬停在特定叶子上时显示。

我试图效仿这个例子无济于事 http://mbostock.github.com/protovis/docs/interaction.html

我到目前为止的代码如下:

var json = {
    "sectors":{
        "electronics": { "Sony": 85, "AMD": 70, "Techtronics": 20, "Apple": 220, "Microsoft": 340},
        "automotive": {"Chevy": 43, "Audi":120, "BMW": 200}},
    "ids":{"Sony":72833,"AMD":582926,"Techtronics":839261, "Apple":822463, "Microsoft":242512, "Chevy":627363, "Audi":524362,"BMW":25143}   
};

var tree = json.sectors;
var ids = json.ids;

var nodes = pv.dom(tree).root("tree").nodes();
color = pv.Colors.category10().by(function(d){return  d.parentNode.nodeName});

var vis = new pv.Panel()
 .width(400)
 .height(400)
 .canvas("test");
var treemap = vis.add(pv.Layout.Treemap)
 .nodes(nodes)
 .round(true);  

treemap.leaf.add(pv.Panel)
 .def("active", false)
 .fillStyle(function(d) d.active ? "lightcoral" : color(d))
 .strokeStyle("#fff")
 .lineWidth(1)
 .antialias(false)
 .cursor("pointer")
 .event("mouseover", function(d) { return this.active(true)});

treemap.label.add(pv.Label)
 .visible(function() {return this.parent.children[0].active()})
 .textStyle(function(d) {return pv.rgb(0, 0, 0, 1)});

vis.render();

1 个答案:

答案 0 :(得分:1)

这里有几个问题:

  • 当您使用.event()方法,时,您传递的函数会返回pv.Mark的实例,Protovis会重新渲染该标记及其子项。 (关于您要返回要重新渲染的标记的要求,文档非常不透明。)

  • 在树形图布局中,标签不是节点的子节点 - 它们是布局的一组独立子节点。因此,当您更新节点时,您将无法获得相应的标签来重新渲染。

  • 你的行中有一个拼写错误:

    .fillStyle(function(d) d.active ? "lightcoral" : color(d))
    

    d是数据,而不是实例。它应该是:

    .fillStyle(function() this.active() ? "lightcoral" : color(d))
    

    但是如上所述,这仍然不会更新标签(虽然我没有过多地使用它,但只需更正此行似乎突出显示所有节点,而不仅仅是您已经结束的节点)

因此,要解决所有这些问题,您需要在active上设置treemap def,而不是在节点上设置。您可以设置活动节点的索引,然后使用相同的索引来引用标签,而不是仅使用true / false:

var treemap = vis.add(pv.Layout.Treemap)
 .nodes(nodes)
 .round(true)
 // define the active node on the layout
 .def("active", -1);  

treemap.leaf.add(pv.Panel)
 .fillStyle(function(d) { 
     return treemap.active() == this.index ? "lightcoral" : color(d) 
 })
 // ...
 .event("mouseover", function() { 
     return treemap.active(this.index);
 })
 .event("mouseout", function() { 
     return treemap.active(-1);
 });

treemap.label.add(pv.Label)
 .visible(function() {
     return treemap.active() == this.index;
 });

Working jsFiddle here.

这里的缺点是你每次都要重新渲染整个树形图。我认为可能只有重新渲染特定节点和标签的方法,但它会更复杂,所以如果性能似乎不是问题,我不会打扰。