【问题标题】:Protovis Treemap - Show labels on hover overProtovis Treemap - 在悬停时显示标签
【发布时间】:2026-02-18 01:45:01
【问题描述】:

我创建了一个树状图。现在我正试图让悬停正常工作。我希望每个 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();

【问题讨论】:

    标签: javascript treemap protovis


    【解决方案1】:

    这里有几个问题:

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

    • 在 Treemap 布局中,标签不是节点的子节点 - 它们是布局的独立子节点组。所以当你更新一个节点时,你不会得到相应的标签来重新渲染。

    • 您在该行中有错字:

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

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

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

      但如上所述,这仍然不会更新标签(虽然我没有过多地使用它,但仅更正这一行似乎会突出显示所有节点,而不仅仅是你结束的那个) .

    所以要解决这一切,你想在treemap 上设置active def,而不是在节点上。你可以设置活动节点的索引,而不是只使用真/假,然后使用相同的索引来引用标签:

    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.

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

    【讨论】:

      最近更新 更多